<p>My application deployed on openshift has url as https://host:port/app/v1/hello/
I am using ServiceAccount as Oauth client and the provider is Openshift, so I should be redirected to Openshift login page for Authorization.</p>
<p>We have configured openshift/oauth-proxy and it works great.
<a href="https://github.com/openshift/oauth-proxy/" rel="nofollow noreferrer">https://github.com/openshift/oauth-proxy/</a></p>
<p>Now further we have requirement of Path based routing, like if URL has /app/v1 then redirect to Service1 and if /app/v2 then to Service2</p>
<p>Here is the working example of my configuration,</p>
<pre><code>`kind: Template
apiVersion: v1
metadata:
  name: deployment-template
objects:
  - apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: my-service-account
      annotations:
        serviceaccounts.openshift.io/oauth-redirectreference.first: '{&quot;kind&quot;:&quot;OAuthRedirectReference&quot;,&quot;apiVersion&quot;:&quot;v1&quot;,&quot;reference&quot;:{&quot;kind&quot;:&quot;Route&quot;,&quot;name&quot;:&quot;my-route&quot;}}'
  - apiVersion: v1
    kind: Service
    metadata:
      name: my-service
      annotations:
        service.alpha.openshift.io/serving-cert-secret-name: proxy-tls
    spec:
      selector:
        app: spring-boot-docker-openshift-hello-world
      ports:
        - name: api
          protocol: TCP
          port: 443 #Port the service listens on.
          targetPort: 8443 #Port on the backing pods to which the service forwards connections.
  - apiVersion: v1
    kind: Route
    metadata:
      name: my-route
    spec:
      port:
        targetPort: api
      path: &quot;/&quot;
      to:
        kind: Service
        name: my-service
      tls:
        termination: Reencrypt
  - apiVersion: apps.openshift.io/v1
    kind: DeploymentConfig
    metadata:
      labels:
        app: spring-boot-docker-openshift-hello-world
        version: 0.0.1-SNAPSHOT.1.dev
      name: spring-boot-docker-openshift-hello-world
    spec:
      replicas: 1
      selector:
        app: spring-boot-docker-openshift-hello-world
      strategy:
        rollingParams:
          timeoutSeconds: 3600
        type: Rolling
      template:
        metadata:
          labels:
            app: spring-boot-docker-openshift-hello-world
            version: 0.0.1-SNAPSHOT.1.dev
        spec:
          serviceAccount: my-service-account
          serviceAccountName: my-service-account
          containers:
          - name: spring-boot-docker-openshift-hello-world
            env:
              - name: KUBERNETES_NAMESPACE
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.namespace
            image: pokarjm/spring-boot-docker-openshift-hello-world:0.0.1-SNAPSHOT.1.dev
            imagePullPolicy: IfNotPresent
            securityContext:
              privileged: false
            ports:
              - containerPort: 8080
                protocol: TCP
          - name: oauth-proxy
            image: openshift/oauth-proxy:latest
            imagePullPolicy: IfNotPresent
            ports:
              - containerPort: 8443
                name: public
            args:
              - --https-address=:8443
              - --provider=openshift
              - --openshift-service-account=my-service-account
              - --upstream=http://localhost:8080
              - --tls-cert=/etc/tls/private/tls.crt
              - --tls-key=/etc/tls/private/tls.key
              - --cookie-secret-file=/etc/proxy/secret/session_secret
              - --openshift-ca=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
              - --openshift-sar={&quot;namespace&quot;:&quot;spring-boot-docker-openshift-hello-world&quot;,&quot;resource&quot;:&quot;services&quot;,&quot;name&quot;:&quot;my-service&quot;,&quot;verb&quot;:&quot;get&quot;}
              - --request-logging=true
            volumeMounts:
              - mountPath: /etc/tls/private
                name: proxy-tls
                readOnly: true
              - mountPath: /etc/proxy/secret
                name: oauth-proxy-secret
                readOnly: true
          volumes:
            - name: proxy-tls
              secret:
                defaultMode: 420
                secretName: proxy-tls
            - name: oauth-proxy-secret
              secret:
                defaultMode: 420
                secretName: oauth-proxy-secret
      triggers:
        - type: ConfigChange
`
</code></pre>
<p>Now to support path based routing, that is map the request /app/v1 to Service1, I just added the Path in route like below,</p>
<pre><code>- apiVersion: v1
    kind: Route
    metadata:
      name: my-route
    spec:
      port:
        targetPort: api
      path: &quot;/app/v1&quot;
      to:
        kind: Service
        name: my-service
      tls:
        termination: Reencrypt
</code></pre>
<p>but with this changes I can see a initial sign in page like below
<img src="https://user-images.githubusercontent.com/8307699/94102883-07017f00-fde8-11ea-8c1d-3e45875e5be6.png" alt="image" /></p>
<p>but after clicking the button above instead of getting the openshift login page, I see below,</p>
<p><img src="https://user-images.githubusercontent.com/8307699/94102957-2e584c00-fde8-11ea-9da2-325a7d55e075.png" alt="image" /></p>
<p>If I change the path in route to path: &quot;/&quot; it works and shows login screen.
Appreciate any help on fixing path based routing in openshift/oauth-proxy.</p>

<p>Try adding something like <code>--proxy-prefix=/app/v1</code>, to your oauth proxy container.</p>
<p>Eg:</p>
<pre><code>[...]
        args:
          - --https-address=:8443
          - --provider=openshift
          - --proxy-prefix=/app/v1
          - --openshift-service-account=my-service-account
[...]
</code></pre>
<p>Otherwise, the oauth-proxy would assume the application it is serving lies at the root of your Route, breaking the login callback redirection.</p>
<p> </p>
<hr />
<p>Now, regarding your question in comments, I'm no sure I got it all myself, I don't have an OpenShift cluster to test this with, ... take it with a pinch of salt, edits welcome, if anyone can get this right.</p>
<p>As far as I understand and recall:</p>
<ul>
<li>Client connect to your app, going through your oauth-proxy.</li>
<li>The proxy sees your client is unauthenticated and requests a token from the Oauth portal, using its client ID and secret (having set <code>openshift-service-account</code>, reads those out of <code>/var/run/secrets/kubernetes.io/serviceaccount/</code>). You could instead use <code>client-id=system:serviceaccount:$ns:$sa</code> and <code>client-secret-file=/var/run/secrets/kubernetes.io/serviceaccount/token</code>, if detection somehow doesn't work.</li>
<li>The Oauth SP checks for our ServiceAccount with an <code>serviceaccounts.openshift.io/oauth-redirectreference</code> <a href="https://docs.openshift.com/container-platform/4.5/authentication/using-service-accounts-as-oauth-client.html" rel="nofollow noreferrer">annotation</a> (though there's another way to do this, with <a href="https://docs.openshift.com/container-platform/4.5/authentication/configuring-internal-oauth.html#oauth-register-additional-client_configuring-internal-oauth" rel="nofollow noreferrer">OauthClient</a>, which I'm less familiar with), matching the client requested application URL. On successful match, SP replies to oauth-proxy with some ephemeral token</li>
<li>Knowing that token, and the <code>proxy-prefix</code>, the oauth-proxy redirects unauthenticated users to the Oauth login portal, with some encoded callback URL as a GET param</li>
<li>User logs in against OpenShift users base</li>
<li>On successful login, the Oauth Portal redirects you to the oauth-proxy, using the callback URL it received from your proxy</li>
<li>the oauth-proxy redeems its token</li>
<li>If <code>openshift-sar</code> was defined, oauth-proxy proceeds with some additional check ensuring client is authorized, otherwise any user may log in</li>
<li>User optionally consent in granting some permissions</li>
</ul>
<p> </p>
<p>In OpenShift context, the initial token requests is done using the <code>login-url</code> param, which defaults to <code>kubernetes.default.svc/oauth/authorize</code>, though in some cases (not sure to remember, some unusual networkpolicies), you may want to force use your OpenShift console FQDN instead.</p>
<p>The token redemption is done through the <code>redeem-url</code> which defaults to <code>kubernetes.default.svc/oauth/token</code>. Again, you could use your public console FQDN here, if SDN otherwise denies this traffic.</p>
<p> </p>
<p><em>So</em>, how is proxy-prefix coming into the picture: only required for your oauth-proxy to build the proper callback URL, for the login form to send you back to the proper sub-path of your application.</p>
<p>And the OAuthRedirectReference is mainly used by OpenShift making sure the client requesting a token is indeed meant to authenticated clients for a given Route. In your case, only matching a FQDN, although I think that in addition to <code>serviceaccounts.openshift.io/oauth-redirectreference.$name: {&quot;kind&quot;: ...}</code>, you may also set something like <code>serviceaccounts.openshift.io/oauth-redirecturi.name: my-path</code></p>
