okta / okta-auth-js

The official js wrapper around Okta's auth API
Other
447 stars 260 forks source link

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

Open djfdev opened 4 years ago

djfdev commented 4 years ago

TLDR:

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.

swiftone commented 4 years ago

@djfdev - Thanks for the report and solid explanation.

Internal ref: OKTA-300072

aarongranick-okta commented 4 years ago

@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!

djfdev commented 4 years ago

@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.

jberube commented 4 years ago

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

swiftone commented 4 years ago

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

kyeotic commented 3 years ago

@swiftone has there been any progress on this?

zaeja commented 3 years ago

@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.

aarongranick-okta commented 3 years ago

@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 commented 3 years ago

@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.

kyeotic commented 3 years ago

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.

aarongranick-okta commented 3 years ago

@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?

kyeotic commented 3 years ago

@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.

aarongranick-okta commented 3 years ago

@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.

kyeotic commented 3 years ago

@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?

swiftone commented 3 years ago

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

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!

kyeotic commented 3 years ago

Awesome! I'm going to test this right now

kyeotic commented 3 years ago

@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 commented 3 years ago

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

kyeotic commented 3 years ago

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

kyeotic commented 3 years ago

@swiftone @aarongranick-okta bump

swiftone commented 3 years ago

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

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 developers@okta.com and they can work with the SDK team.

Hope that helps!

kyeotic commented 3 years ago

@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.

aarongranick-okta commented 3 years ago

@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

kyeotic commented 2 years ago

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

aarongranick-okta commented 2 years ago

@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"

ashwini-desai commented 2 years ago

@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?

denysoblohin-okta commented 1 year ago

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?
kyeotic commented 1 year ago
  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.
m-mohr commented 6 months ago

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?!

arvssynd commented 2 months ago

Hi, I have problem maybe connected to this thread, when I call the SignOut method an "oauth2" it's being added to the api path, but "oauth2" it's not specified anywhere. This is the api url generated for the logout (which generates an error)

This is (I assume) the correct logout url

Is there a away to avoid this behavior?

This is our SignOut configuration this._oktaAuth.signOut({ accessToken: authState?.accessToken, idToken: authState?.idToken, revokeAccessToken: true, clearTokensBeforeRedirect: true, postLogoutRedirectUri: https://oururl.com/logout })

where none of the tokens contains a reference to "oauth2".

Is there a solution?

jaredperreault-okta commented 2 months ago

@arvssynd Can you please create a new issue?