Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support PKCE client flows #132

Open
bdemers opened this issue Jun 5, 2019 · 12 comments
Open

Support PKCE client flows #132

bdemers opened this issue Jun 5, 2019 · 12 comments

Comments

@bdemers
Copy link
Contributor

bdemers commented Jun 5, 2019

Client support for PKCE has been added in the next Spring Security Release

We have a few places we check if the client-secret is set. This needs to be removed and ONLY check for client-id. All that is needed is an issuer and a client-id (assuming PKCE is enabled)

@mraible
Copy link
Contributor

mraible commented Oct 8, 2019

From the Spring Security 5.2.0 docs:

PKCE will automatically be used when the following conditions are true:

  • client-secret is omitted (or empty)
  • client-authentication-method is set to "none" (ClientAuthenticationMethod.NONE)

I tried the following in application.properties with Okta Boot 1.2.1 and Spring Boot 2.2.0.RC1.

spring.security.oauth2.client.provider.okta.issuer-uri=https://dev-xxxxxx.okta.com/oauth2/default
spring.security.oauth2.client.registration.okta.client-id=xxx
spring.security.oauth2.client.registration.okta.client-authentication-method=none

This results in:

[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: 401 Unauthorized

I also tried using Okta properties:

okta.oauth2.issuer=https://dev-xxxxxx.okta.com/oauth2/default
okta.oauth2.client-id=xxx
okta.oauth2.client-authentication-method=none

However, this results in the same error.

@jasonrberk
Copy link

I am also having issues using Okta spring boot v1.2.1 with boot 2.1.4.RELEASE. I have no client-secret. My UI is using PKCE and I have a client ID and issuer

@bdemers
Copy link
Contributor Author

bdemers commented May 22, 2020

Hey @jasonrberk!
I think Matt might have mentioned this on another thread, but you don't need PKCE support for resource servers, you would only use PKCE where you are getting the token. Once you have the token you just send it to your resource server in a header Authorization: Bearer <your-access-token>

@jasonrberk
Copy link

jasonrberk commented May 22, 2020 via email

@bdemers
Copy link
Contributor Author

bdemers commented May 22, 2020

I'd suggest isolating the front end vs the backend.

Can you access your resource server using curl/httpie? If that fails in the same way. My next suggestion is to turn up the logging in your spring boot app. Spring Security by default doesn't log much (for good reason), setting the root log level to DEBUG is a pretty verbose, but it's helped me figure out these types of issues.

My next suggestion would be to include the decoded token from: https://www.jsonwebtoken.io/
You can censor the info hostname, user, email, etc.
A few of the key elements to look for is the issuer should be formatted something like:
https://${yourOktaDomian}/api/v1/authorizationServers/${id} (where id is usually the word "default")
The aud claim by default is api://default, if either of those are different the token validation would fail.

@jasonrberk
Copy link

jasonrberk commented May 22, 2020

I'd suggest isolating the front end vs the backend.

that's what I'm trying to do now....

Can you access your resource server using curl/httpie?

that's how I'm testing my API.....I'm cURL'ing it with my token and only getting a 401

curl -H "Authorization: Bearer $TOKEN" -H 'Accept: application/json' localhost:8080/api/user/config

If that fails in the same way. My next suggestion is to turn up the logging in your spring boot app. Spring Security by default doesn't log much (for good reason), setting the root log level to DEBUG is a pretty verbose, but it's helped me figure out these types of issues.

I'll give that a shot...

My next suggestion would be to include the decoded token from: https://www.jsonwebtoken.io/
You can censor the info hostname, user, email, etc.
A few of the key elements to look for is the issuer should be formatted something like:
https://${yourOktaDomian}/api/v1/authorizationServers/${id} (where id is usually the word "default")
The aud claim by default is api://default, if either of those are different the token validation would fail.

my decoded (and edited) token:

{
  "ver": 1,
  "jti": "AT.mNwHKFlgnzwYSKuuaiWIxqAwiE502GXGV3Hvw6em999",
  "iss": "https://foo.oktapreview.com",
  "aud": "https://foo.oktapreview.com",
  "sub": "[email protected]",
  "iat": 1590156389,
  "exp": 1590159989,
  "cid": "0oarm68ub9999lED00h7",
  "uid": "00unbhyky99991zFS0h7",
  "scp": [
    "openid",
    "profile",
    "email"
  ]
}

@jasonrberk
Copy link

spring security debug logs show this error:

Authentication request for failed: org.springframework.security.oauth2.core.OAuth2AuthenticationException: An error occurred while attempting to decode the Jwt: Couldn't retrieve remote JWK set: org.springframework.web.client.HttpClientErrorException$NotFound: 404 Not Found

@bdemers
Copy link
Contributor Author

bdemers commented May 22, 2020

Ahh, the issuer is the problem. This type of toke is from the root Okta issuer, and cannot be validated as a JWT (even though it is formatted as one). You need to use one formatted as I mentioned above.

Access tokens are opaque strings per the OAuth spec, and are validated remotely. You can do this with Spring Boot/Security out of the box (without the Okta Starter), by configuring the resource server to be “opaque”.

Typically we just recommend to use a “custom” authorization server though.

(I’m typing on my phone otherwise a I’d dig up an example)

Keep us posted!

@jasonrberk
Copy link

jasonrberk commented May 22, 2020 via email

@jasonrberk
Copy link

I want my API (resource server) to only allow requests from callers that have an access token issued by okta specifically to users of my SPA.

sounds like I need to create users and groups in Okta, and an "application"....tie these altogether and setup an Auth Server that is tied to the client ID of my app.

the key for me, is that ONLY the users who authenticate with Okta for MY CLIENT should be allowed to access the resource server. An access token issued by my okta instance alone is not good enough. In other words, an access token received when using SPA "foo" would not allow you to call the API for the "bar" resource server. Only the token provided when logging in to SPA "bar" would pass the auth test.

make sense?

@bdemers
Copy link
Contributor Author

bdemers commented May 22, 2020

Yes, using a custom Authorization Server fils this exact use case. My suggestion would be to create an Auth server and set the “audience” to something specifics for your app, then configure this starter to validate against that.

@jasonrberk
Copy link

@bdemers can you help me with https://stackoverflow.com/questions/62227762/spring-security-filter-issues. It appears as if the filter created by the okta starter is being greedy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants