oktadev / okta-spring-boot-2-angular-7-example

A Cool Cars Example that showcases Spring Boot 2.1, Angular 7, and Okta's support for both.
https://developer.okta.com/blog/2018/08/22/basic-crud-angular-7-and-spring-boot-2
Apache License 2.0
86 stars 67 forks source link

String Index Out Of Range (bare) / 401 (with /oauth2/default) - when using example #7

Open MarcelTon opened 5 years ago

MarcelTon commented 5 years ago

I can not run the server with "our company" configuration and am unsure why. After creating an SPA Client in Okta with OpenID Connect I clone the project. I adjust the configuration as follows:

  1. http://localhost:4200/implicit/callback set as Login redirect URI in Okta
  2. Adjust my application yaml and app module typescript as shown below
  3. Test if https://company.okta.com/.well-known/openid-configuration works (it does with the real company name)

application.yml:

    okta:
      oauth2:
        client-id: 20-digit-Client-ID-string
        issuer: https://company.okta.com

app.module.ts:

    const config = {
      issuer: 'https://company.okta.com',
      redirectUri: 'http://localhost:4200/implicit/callback',
      clientId: '20-digit-Client-ID-string'
    };

Java version:

java version "1.8.0_192"
Java(TM) SE Runtime Environment (build 1.8.0_192-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.192-b12, mixed mode)

Maven version:

Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-24T20:41:47+02:00)
Maven home: /usr/local/Cellar/maven/3.6.0/libexec
Java version: 1.8.0_192, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk1.8.0_192.jdk/Contents/Home/jre
Default locale: en_NL, platform encoding: UTF-8
OS name: "mac os x", version: "10.13.6", arch: "x86_64", family: "mac"

JAVA_HOME:

/Users/m.ton/.jenv/versions/oracle64-1.8.0.192

If I then run ./mvnw spring-boot:run from the server folder I get the following error:

[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.0.RELEASE:run (default-cli) on project demo: An exception occurred while running. null: InvocationTargetException: Error creating bean with name 'okta.client-com.okta.spring.config.OktaClientProperties': Could not bind properties to 'OktaClientProperties' : prefix=okta.client, ignoreInvalidFields=false, ignoreUnknownFields=true; nested exception is org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'okta.client.org-url' to java.lang.String: String index out of range: -1 -> [Help 1]

If I change my config to the below "default" from the clone my backend runs just fine.

application.yml:

    okta:
      oauth2:
        client-id: 0oagqzcu86BBOq2jF0h7
        issuer: https://dev-737523.oktapreview.com/oauth2/default

Obviously I can't onboard users that way haha, but it runs. If I use https://company.okta.com/oauth2/default by the way (this isn't what is shown in the Issuer field in Okta, but just in case) I receive the following error:

[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.0.RELEASE:run (default-cli) on project demo: An exception occurred while running. null: InvocationTargetException: Failed to process import candidates for configuration class [org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerConfiguration]; nested exception is java.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerTokenServicesConfiguration$JwkTokenStoreConfiguration: 401 Unauthorized -> [Help 1]

Could you tell me what I can try/provide to get it running on my machine? I'm at my wits end. Using Java11 + the Issuer as shown in Okta gives the same error, albeit formatted a little differently:

[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.0.RELEASE:run (default-cli) on project demo: An exception occurred while running. null: InvocationTargetException: Error creating bean with name 'okta.client-com.okta.spring.config.OktaClientProperties': Could not bind properties to 'OktaClientProperties' : prefix=okta.client, ignoreInvalidFields=false, ignoreUnknownFields=true; nested exception is org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'okta.client.org-url' to java.lang.String: begin 0, end -1, length 25 -> [Help 1]
bdemers commented 5 years ago

Hey @MarcelTon!

Okta has two different types of issuers one for the Okta Dashboard/Admin console this is typically formatted as https://company.okta.com the other is for API Access Management (any of your applications) and is typically seen as: https://company.okta.com/oauth2/default

Our Spring integration performs local validation of the access token by default, and this can ONLY be done for the API Access Management issuer (so this is likely why one worked and the other didn't)

You can work around this by validating the access token remotely by setting the property okta.oauth2.localTokenValidation=true (or equivalent yaml). That said, Spring Security 5, does NOT yet support remote token validation. So this is a bit of a dead end for the short term (and because of this, this property will NOT work with our major next release)

The easiest path forward is to use the /oauth2/default style issuer.

Which leads us to the 401, I'm not following this part completely, you mentioned said it worked well, but in some cases you get a 401? Can you clarify this part?

MarcelTon commented 5 years ago

Hi @bdemers , thank you for your quick response. I have removed the part of my colleague being able to run the server, miscommunication. He can get a flow working with just the client, but obviously doesn't get any cool car list!

My title was unclear, I will try to clarify on the 401 (1 and 2) and would like to ask a follow-up question regarding the API Access Management issuer (3).

  1. When using the config issuer: https://company.okta.com for the server I receive the InvocationTargetException with the "String index out of range".
  2. When using the config issuer: https://company.okta.com/oauth2/default for the server I receive the IllegalStateException with the "JwkTokenStoreConfiguration: 401 Unauthorized".

This is reproducible behaviour simply done by a fresh checkout (and verified by my colleagues so I was sure I wasn't losing it), changing the two config parameters and running ./mvnw spring-boot:run from the server dir. The problem might very well lie with the 401, I just don't really know where to proceed in Okta to solve this access problem!

  1. What do you mean by the API Access Management "issuer"? The server run doesn't know anything of the user that started the run does it?

I will play around with the LocalTokenValidation and see if it offers more insight, thank you again!

EDIT: I removed the "it works for my colleague"-stuff, we all can not run the server app and have the same errors for java8 and java11.

bdemers commented 5 years ago

@MarcelTon

What comes back from a request to https://company.okta.com/oauth2/default/.well-known/openid-configuration (from your browser)?

Swicchi commented 5 years ago
  1. When using the config issuer: https://company.okta.com for the server I receive the InvocationTargetException with the "String index out of range".

I think that you should set the org-url: okta.client.org-url= https://company.okta.com

Swicchi commented 5 years ago

For a https://company.okta.com server without Authorization server, you must validate the idToken, you need set security.oauth2.resource.jwk.key-set-uri=https://company.okta.com/oauth2/v1/keys security.oauth2.client.client-id={$client.id} in your application.properties and remove the okta oauth2. And you need add:

@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
    resources.resourceId("${aud}");
}

in the ResourceServerConfigurerAdapter class.