okta-auth-js icon indicating copy to clipboard operation
okta-auth-js copied to clipboard

Use well-known configuration to infer token issuer and authorization server endpoints

Open djfdev opened this issue 4 years ago • 31 comments

TLDR:

  • It looks like the PKCE flow breaks when the base URL of well-known config is not the same as the issuer claim in the token
  • The well-known config returns all the necessary information needed to authorize the client, get a token, and validate its issuer claim, so it could be used for this.

Long version:

I'm running into a problem with this SDK because my well-known config endpoint is not the same base as the issuer of my tokens. And because the SDK validates the issuer of the token against what is passed in as the issuer parameter and uses this parameter to form the endpoint for the well-known request, it seems I cannot do both.

If the SDK is already requesting the well-known configuration in the PKCE flow, why not use the response to infer all of the other information needed about the authorization server? The configuration returns the issuer of the token, so that should be used to validate the token when it is received. Furthermore, the configuration returns the authorization_endpoint and token_endpoint, which could be used in place of the authUrl and tokenUrl SDK options.

In an ideal world, the issuer would not be a required option for the Okta SDK, and instead I could just supply a wellKnownUrl or something similar to get all the information needed to complete my auth flow.

djfdev avatar May 20 '20 23:05 djfdev

@djfdev - Thanks for the report and solid explanation.

Internal ref: OKTA-300072

swiftone avatar May 22 '20 18:05 swiftone

@djfdev We are investigating this issue and working on a better solution for url discovery. In the meantime, it may work for you to explicitly set the authorizeUrl or tokenUrl on the config:

https://github.com/okta/okta-auth-js#additional-options

Please let us know if this will function as a workaround. Thanks!

aarongranick-okta avatar Jun 12 '20 18:06 aarongranick-okta

@aarongranick-okta that's what we are doing now, and it works but it is not an ideal solution.

We have what is perhaps a unique situation, in that we use a proxy to communicate with the Okta authorization server(s). So the base URL of the well-known config endpoint is not the same as the issuer of the token. For now, we provide the authorization server URL for the issuer parameter, and our proxy URLs for the authUrl and tokenUrl parameters. Ideally we would just provide a single configuration parameter for the well-known config, from which the token issuer and other endpoints would be inferred.

djfdev avatar Jun 12 '20 18:06 djfdev

@swiftone does OKTA-300072 also applies to implicit flow ?

jberube avatar Jul 15 '20 15:07 jberube

@jberube - yes, the goal of that ticket is to rely on .well-known for endpoints unless specifically overridden, for all flows

swiftone avatar Jul 22 '20 20:07 swiftone

@swiftone has there been any progress on this?

kyeotic avatar Jan 12 '21 23:01 kyeotic

@swiftone I'm also interested to hear if there's been any movement on this issue - we are running into the same problem for a browser app currently using okta-react that previously only supported a direct connection to Okta authorisation servers, but which we would like to also enable support for AWS cognito acting as a proxy between them.

Unfortunately in this scenario the well-known config is hosted at a completely different domain to the issuer with the other flow urls, so we are leaning towards reworking our app with another library. This enhancement would instead resolve the problem, I think.

zaeja avatar Feb 16 '21 19:02 zaeja

@zaeja Can you provide a little more detail on the "enhancement" you are looking for? If I understand correctly you are using a proxy, so the issuer and authorizeUrl that you would like the app to use for the network request will be different from the values returned from the .well-known endpoint (and included in the token's claims).

Are you looking to skip or customize the validation logic here? https://github.com/okta/okta-auth-js/blob/master/lib/oidc/util/validateClaims.ts#L34

The original issue said: "In an ideal world, the issuer would not be a required option for the Okta SDK, and instead I could just supply a wellKnownUrl or something similar to get all the information needed to complete my auth flow."

I think a wellKnownUrl option in this case would still return an issuer / authorizeUrl that is not behind the proxy. So I'd like to get into more detail on the specific enhancements we could do to support your case.

aarongranick-okta avatar Feb 16 '21 19:02 aarongranick-okta

@djfdev The issuer returned from the .well-known endpoint should match the HOST header of the request. If you have a custom Okta domain setup and hit my.domain.com/.well-known/openid-configuration it should return my.domain.com as the issuer.

If you are seeing the issuer NOT matching the HOST header, there may be something misconfigured in your organization's settings. If this is the case, Okta support can help resolve this.

aarongranick-okta avatar Feb 16 '21 19:02 aarongranick-okta

This isn't an okta proxy, its a company proxy. The issuer doesnt match because the issuer is still an okta domain; it has to match the actual issuer on the token that okta returns. We can't make the issuer match the proxy because the proxy isn't minting tokens.

kyeotic avatar Feb 16 '21 21:02 kyeotic

@kyeotic Makes sense. I can think of a couple ways to solve this problem. One would be to intercept at the network layer to request from the proxy instead of the "original" URL. This could use some kind of map from original URL -> proxy URL.

This could be done with the current version using the httpRequestClient option.

Another way would be to bypass/customize the validation logic here. This would require some changes in the SDK.

I'm sure there are other ways to accomplish this. Do you have a specific idea of how you would like to see this scenario supported?

aarongranick-okta avatar Feb 16 '21 23:02 aarongranick-okta

@aarongranick-okta

I'd like to avoid intercepting calls and modifying them, if possible. I'd like to see this solved by changing the validation logic so that the token issuer only had to match the issuer returned by the .well-known endpoint. There shouldn't need to be a relationship between the host/domain of the .well-known endpoint and its response contents.

Our .well-known endpoint's response includes the correct okta issuer, which will match the token. This library doesn't like it, but there doesn't seem to be a good reason to override the .well-known response with the assumption that it should match the .well-known's host/domain.

The logic you linked is correct, I think it's just being provided with the wrong parameters. The iss should come exclusively from the .well-known response instead of being derived from other values.

Edit: btw @djfdev has moved on to greener pastures, I'm working the original story he raised this issue for.

kyeotic avatar Feb 16 '21 23:02 kyeotic

@kyeotic Thanks, that makes sense. Currently the issuer from the token is compared with the configured issuer, but it can (should) be compared with the issuer returned from well-known. I have updated the notes on the internal issue. I'm hoping we can get a solution out to you quickly.

aarongranick-okta avatar Feb 16 '21 23:02 aarongranick-okta

@aarongranick-okta I might be reading GitHub incorrectly, but it looks like that linked PR was approved and then closed without being merged. Are you still planning to handle this issue?

kyeotic avatar Mar 17 '21 21:03 kyeotic

@kyeotic - you aren't reading github wrong, but our bot interacts with github oddly. The code from the PR was merged:

  • you can see it on the list here: https://github.com/okta/okta-auth-js/commits/master
  • and as this item in the master commit history: https://github.com/okta/okta-auth-js/commit/756a46079921130a256ac141ccbd7ac2a5716927

But the PR itself is just marked as "Closed". Our bot commits the code after our internal tests pass, and unfortunately it doesn't do a great job of marking the PR as merged. We have a task to improve that, but naturally fixes like this one take priority over that messaging.

This fix was included in 4.8.0 of okta-auth-js: https://github.com/okta/okta-auth-js/releases/tag/okta-auth-js-4.8.0

Hope that helps!

swiftone avatar Mar 17 '21 21:03 swiftone

Awesome! I'm going to test this right now

kyeotic avatar Mar 17 '21 21:03 kyeotic

@swiftone I can't figure out how to configure this correctly. There isn't a documented path to just provide the .well-known endpoint directly, it appears to generate it based on the issuer.

Lets say I have our well-known proxy at https://oauth-proxy.com/v1/qa/.well-known/openid-configuration. It returns the following

{
"issuer":"https://company.oktapreview.com/oauth2/custom_auth_server_id",
"authorization_endpoint":"https://oauth-proxy.com/v1/qa/authorize",
"token_endpoint":"https:/oauth-proxy.com/v1/qa/token"
}

The authorization_endpoint and token_endpoint perform redirects to the correct custom auth server.

If I just provide issuer: https://oauth-proxy.com/v1/qa/ it tries to redirect to https://oauth-proxy.com.com/v1/qa/oauth2/v1/authorize. Where did it get this value from?

If I manually set the authorizeUrl and tokenUrl on the config to the proxy values above it signs in, but then still fails with the same "issuer does not match" error, since its comparing the real https://company.oktapreview.com/oauth2/custom_auth_server_id value against the proxy isssuer from the config.

kyeotic avatar Mar 18 '21 17:03 kyeotic

@aarongranick-okta #646 does not appear to be functioning as intended

kyeotic avatar Mar 23 '21 16:03 kyeotic

@swiftone @aarongranick-okta <friendly reminder that this is broken>

kyeotic avatar Mar 30 '21 16:03 kyeotic

@swiftone @aarongranick-okta bump

kyeotic avatar May 06 '21 20:05 kyeotic

@kyeotic - I've left Okta so I'm afraid I can't be very helpful. But, looking at the linked PR:

  • As you say, you can't set the well-known endpoint, it is based off of the issuer given to auth-js
  • the validationOptions should auto-populate based on the info from the well-known endpoint, or you can override those defaults with manual values
  • the validationOptions apply only to validating the issued tokens, not to generating them (so the authorize enpoint you mention is likewise based off of the passed issuer)

I suspect this is a disagreement about what calls your proxy is...proxying, and what calls Okta expects to be proxied. If you can describe a bit more which calls are proxied I assume the Okta staff can give you a better answer (or find what the code does not yet cover). If you would prefer to be detailed but non-public in your description, Okta has a support team that can be reached at [email protected] and they can work with the SDK team.

Hope that helps!

swiftone avatar May 06 '21 20:05 swiftone

@swiftone Thank you, I will try to keep going with another maintainer.

@shuowu-okta @vijetmahabaleshwar-okta You've both responded to Swiftone's, are you able to direct this ticket to someone who can assist? It seems there has been a misunderstanding in implementing this feature.

As you say, you can't set the well-known endpoint, it is based off of the issuer given to auth-js

This entire isssue is about the ability to set the well-known endpoint. Our well-known endpoint does not have the same domain as our issuer, since the issuer is Okta and our well-known endpoint is a company proxy. Without the ability to set a well-known endpoint this issue remains unsolved.

kyeotic avatar May 07 '21 15:05 kyeotic

@kyeotic Many apologies for this issue falling through a crack, I have confirmed this issue still exists and was not fixed by #646

We have re-prioritized this issue and are currently working on a proper fix. internal ref: OKTA-409981

aarongranick-okta avatar Jul 08 '21 21:07 aarongranick-okta

@aarongranick-okta Has there been any progress on this?

kyeotic avatar Nov 04 '21 22:11 kyeotic

@kyeotic It looks like this issue should have been fixed with https://github.com/okta/okta-auth-js/pull/858

You should be able to use your frontend proxy URL as the "issuer"

aarongranick-okta avatar Nov 05 '21 00:11 aarongranick-okta

@aarongranick-okta - #858 Doesn't seem to have fixed this. In fact there is a test which says "will always use issuer from well-known openid-configuration" in this PR.

We are also not able to use the proxy by setting authUrl and tokenUrl as mentioned. We tried this with latest(5.8.0) version of okta-auth-js too. Can you help us with this?

ashwini-desai avatar Dec 03 '21 05:12 ashwini-desai

Sorry for a late reply to pretty old issue. I'd like to gather more information about using proxies with Okta and okta-auth-js and would appreciate any feedback.

  1. What's the intention to use a proxy to communicate with the Okta authorization server(s), and for token endpoint? What problem can it solve?
  2. Can using a custom domain solve this issue?
  3. Does your Okta org use Identity Engine, and application uses Interaction Code flow?

@djfdev @ashwini-desai You can use authorizeUrl (not authUrl) and tokenUrl in configuration options for latest okta-auth-js versions. Does it work for you?

@kyeotic

  1. authorization_endpoint and token_endpoint returned from .well-known/openid-configuration are not currently used for overriding configuration in okta-auth-js, but you can use authorizeUrl and tokenUrl options. Is this sufficient or you want to rely on well-known response (maybe for dynamic configuration)?
  2. You said "The authorization_endpoint and token_endpoint perform redirects to the correct custom auth server." Does it mean your https://oauth-proxy.com/v1/qa/authorize would just redirect to https://company.oktapreview.com/oauth2/v1/authorize with 302 status code, or really proxy responses?

denysoblohin-okta avatar Jan 31 '23 21:01 denysoblohin-okta

  1. No, we need to use the response from well-known. I know they are not currently used, this was a request for a change to the library. FWIW, the change we are requesting is that this library use the configuration that it gets from the the endpoint that the oAuth spec says holds configuration. This change was agreed to. Are we back to discussing whether or not to do it?
  2. It redirects with a 302.

kyeotic avatar Feb 02 '23 23:02 kyeotic

I'm facing the same issue. It looks like this library is not OIDC compliant, it doesn't use the values provided in the well-known document, but instead uses some pre-configured values in the code (i.e. in getOAuthUrls). I don't quite understand why the librar doesn't use the well-known document for OIDC? That's what it is meant to be used for. I guess this library is meant to be only used with the pure OktaAuth service, not as a general OIDC library, unfortunately?!

m-mohr avatar Mar 22 '24 11:03 m-mohr