Get react-oidc-context to register login if OAuth provider signin redirect has custom token parameter

118 Views Asked by At

Unusual customer OAuth params

My customer has their own OAuth provider which I must use. Their flow requires that to sign in, my app redirects to

customer-oauth/account/signin?redirect=<redirect_url>&some=custom&params=needed

Once the user logs in there, they are returned to my app, at the url redirect_url?customer_portal_token=<some_token>

Note the customer_portal_token, a custom param they use. Once they are redirected, I must call customer-oauth/auth/get-token with the customer_portal_token short-lived token, which will return me a new access_token.

oidc-client-ts and react-oidc-context setup

Before understanding their non-standard naming convention, I had set my app up with oidc-client-ts with react, via react-oidc-context, as I've done many times before with something like keycloak:

import { AuthProvider, AuthProviderProps } from "react-oidc-context";

const oidcConfig: AuthProviderProps = {
  authority: AUTHORITY,
  redirect_uri: MY_APP_URL,
};

const App = () => {
  return (
    <AuthProvider {...oidcConfig}>
      <AppHere />
    </AuthProvider />
  )
}
import { useAuth } from "react-oidc-context";

const DeeperInTheApp = () => {

  const { isAuthenticated, signinRedirect, signoutRedirect } = useAuth();

  return isAuthenticated 
    ? <button onClick={() => signinRedirect()}>logout</button> 
    : <button onClick={() => signoutRedirect()}>login</button>
}

The happy path with keycloak

This works well with keycloak. With keycloak, when the login button is clicked, a call to KEYCLOAK_URL/realms/master/.well-known/openid-configuration is made, and the oidc metadata has the url of the signin url, as well as the token url. The user is redirected to the signin url, where they log in. On login success, they are returned to my app at the url of something like redirect_url?state=<hash>&session_state=<hash>&iss=<redirect_url>&code=<code_hash>. A call is made to the token route from the well-known call using the params in that signin redirect url, and a response is gotten with things like id_token, acess_token, refresh_token, etc. The react-oidc-context is then considered "logged in", as expected.

Massaging customer custom OAuth params into this setup

In my case, there is no metadata route for the oidc. So I have to provide that manually in my oidcConfig:

const oidcConfig: AuthProviderProps = {
  authority: CUSTOMER_OIDC,
  metadata: {
    issuer: CUSTOMER_OIDC,
    authorization_endpoint: `${CUSTOMER_OIDC}/account/signin`,
    token_endpoint: `${CUSTOMER_OIDC}/get-refresh`,
  },
};

With some custom params on sign-in:

const DeeperInTheApp = () => {

  const { isAuthenticated, signinRedirect, user, signoutRedirect } = useAuth();

  return isAuthenticated 
    ? <button 
        onClick={() => signinRedirect(
          extraQueryParams({
            some: 'custom',
            params: 'needed'
          })
        )}>
        logout
      </button> 
    : <button onClick={() => signoutRedirect()}>login</button>
}

This works - when I click the login butto, signinRedirect is called. I am taken to the customer's OAuth portal, with all the correct custom params put in, with my app's url as the redirect url. After sign-in, I am taken back to my app.

But now instead of oidc-client-ts knowing to call the token_endpoint with the param customer_portal_token=<the_token_from_signin_redirect>, nothing happens.

How can I push oidc-client-ts and react-oidc-context to take this final step, and call the customer's custom token endpoint, with the custom customer_portal_token param that is found in the signin redirect url? I want to leverage all the existing functionality of oidc-client-ts and react-oidc-context without having to basically write my own auth handler. Seems like I should be able to coax the libraries into calling the token route with the custom param, saving the response in the react-oidc-context state, and have the oidc-context consider the app authenticated.

Is this possible?

0

There are 0 best solutions below