Skip to content

Consider adding switch to enable or disable OIDC nonce #7696

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

Closed
hejianchao opened this issue Dec 4, 2019 · 26 comments · Fixed by #7748
Closed

Consider adding switch to enable or disable OIDC nonce #7696

hejianchao opened this issue Dec 4, 2019 · 26 comments · Fixed by #7748
Assignees
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) type: enhancement A general enhancement
Milestone

Comments

@hejianchao
Copy link

hejianchao commented Dec 4, 2019

@hejianchao No there isn't a setting/property available to turn it off. Are you having issues with it? Why do you want it disabled?

Originally posted by @jgrandja in #4442 (comment)

This issue was created for two reasons:

  1. Some cloud vendors do not fully support OIDC nonce, and an error will be reported: invalid nonce
  2. OpenID Connect Core 1.0, Section 3.1.2.1, "nonce" parameter:

nonce
OPTIONAL. String value used to associate a Client session with an ID Token, and to mitigate replay attacks. The value is passed through unmodified from the Authentication Request to the ID Token. Sufficient entropy MUST be present in the nonce values used to prevent attackers from guessing values. For implementation notes, see Section 15.5.2.

Also, as far as I know, the pac4j framework supports nonce settings (link).

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Dec 4, 2019
@hejianchao hejianchao changed the title Support switch to enable or disable OIDC nonce Consider adding switch to enable or disable OIDC nonce Dec 4, 2019
@jgrandja
Copy link
Contributor

jgrandja commented Dec 6, 2019

@hejianchao Regarding your comment:

Some cloud vendors do not fully support OIDC nonce, and an error will be reported: invalid nonce

If this is the case than the provider is NOT OpenID Connect compliant.

As per spec, in the ID Token section:

String value used to associate a Client session with an ID Token, and to mitigate replay attacks. The value is passed through unmodified from the Authentication Request to the ID Token. If present in the ID Token, Clients MUST verify that the nonce Claim Value is equal to the value of the nonce parameter sent in the Authentication Request. If present in the Authentication Request, Authorization Servers MUST include a nonce Claim in the ID Token with the Claim Value being the nonce value sent in the Authentication Request. Authorization Servers SHOULD perform no other processing on nonce values used. The nonce value is a case sensitive string.

The Authorization Server MUST include the nonce Claim in the ID Token if it was sent in the Authentication Request.

If you need to override the Authentication Request to not include the nonce parameter than you can supply oauth2Login().authorizationEndpoint().authorizationRequestResolver() a custom OAuth2AuthorizationRequestResolver that removes the nonce parameter. Take a look at the reference doc for an example of how to implement.

@jgrandja jgrandja added in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) status: waiting-for-feedback We need additional information before we can continue and removed status: waiting-for-triage An issue we've not yet triaged labels Dec 6, 2019
@jgrandja jgrandja self-assigned this Dec 6, 2019
@hejianchao
Copy link
Author

@jgrandja It works but not so convenient, For optional parameters like nonce, switches are a more convenient way. Anyway, thanks for your information.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Dec 7, 2019
@jgrandja
Copy link
Contributor

jgrandja commented Dec 8, 2019

@hejianchao

Some cloud vendors do not fully support OIDC nonce, and an error will be reported: invalid nonce

Which provider are you having this issue with? Could you provide more details around the error message? Is the error message being triggered by the provider or client?

@jgrandja jgrandja removed the status: feedback-provided Feedback has been provided label Dec 8, 2019
@hejianchao
Copy link
Author

The method that throws the exception is: org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizationCodeAuthenticationProvider#authenticate:

// Validate nonce
String requestNonce = authorizationRequest.getAttribute(OidcParameterNames.NONCE);
if (requestNonce != null) {
	String nonceHash;
	try {
		nonceHash = createHash(requestNonce);
	} catch (NoSuchAlgorithmException e) {
		OAuth2Error oauth2Error = new OAuth2Error(INVALID_NONCE_ERROR_CODE);
		throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
	}
	String nonceHashClaim = idToken.getNonce();
	if (nonceHashClaim == null || !nonceHashClaim.equals(nonceHash)) {
                // Here thrown the exception because nonceHashClaim is null
		OAuth2Error oauth2Error = new OAuth2Error(INVALID_NONCE_ERROR_CODE);
		throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
	}
}

@jgrandja
Copy link
Contributor

jgrandja commented Dec 9, 2019

@hejianchao Which provider are you using?

@jgrandja jgrandja added the status: waiting-for-feedback We need additional information before we can continue label Dec 9, 2019
@soarten
Copy link

soarten commented Dec 13, 2019

I also ran into this issue using a proprietary in house IdP from a large organization. This IdP provides a limited openid feature set and does not support nonce parameters. It does however integrate with well known clients like Keycloak and others.

Although one can navigate around this problem as was suggested above. This is not a very clean solution. It would be nice to have a switch to disable requesting nonces.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Dec 13, 2019
@jgrandja jgrandja added type: enhancement A general enhancement and removed status: feedback-provided Feedback has been provided labels Dec 17, 2019
@jgrandja jgrandja added this to the 5.3.0.M1 milestone Dec 17, 2019
@jgrandja
Copy link
Contributor

jgrandja commented Dec 17, 2019

@hejianchao @soarten I took a look at pac4j and I see that it provides a switch setUseNonce(true). I'm not a fan of this approach since every extended parameter would need an associated setUseExtendedParameter(true). And there are quite a few OIDC specific extension parameters. This will quickly make DefaultOAuth2AuthorizationRequestResolver unwieldy.

Instead of the switch approach, we're looking at introducing a Consumer<OAuth2AuthorizationRequest.Builder> #7748, that should allow easier customizations. For excluding the nonce, take a look at this test.

Let me know your thoughts.

@hejianchao
Copy link
Author

@jgrandja Great, through Consumer<OAuth2AuthorizationRequest.Builder>, it can be more flexible and convenient for users to control the request, which solved my problem. Thank you.

@soarten
Copy link

soarten commented Dec 18, 2019

Using switches for all sorts of options is far from ideal indeed, this would be a better solution!

@eleftherias eleftherias modified the milestones: 5.3.0.M1, 5.3.0.RC1 Jan 8, 2020
@eleftherias eleftherias removed this from the 5.3.0.RC1 milestone Feb 5, 2020
@eleftherias eleftherias added this to the 5.3.0 milestone Feb 5, 2020
@jadzie
Copy link

jadzie commented Mar 17, 2020

@jgrandja I think there's a problem with OAuth2AuthorizationRequest.Builder.attributes method - it is called by default from DefaultOAuth2AuthorizationRequestResolver.resolve, setting up an attributesConsumer within the Builder which captures the attributes (it does putAll from captured attributes to a new map when the request is built, OAuth2AuthorizationRequest line 446).
If anyone uses the configurer (replacing the "putAll" attributesConsumer), those attributes are effectively lost.

@jgrandja
Copy link
Contributor

@jadzie Can you put together a minimal sample or a test that reproduces the issue. This will make it more clear to me if there is an issue or not.

@jadzie
Copy link

jadzie commented Mar 17, 2020

@jgrandja ok, will try to do it for tomorrow

@jadzie
Copy link

jadzie commented Mar 18, 2020

@jgrandja https://github.com/jadzie/login-oidc-customizer-test I hope the readme is descriptive enough :)

@jgrandja
Copy link
Contributor

Thank you for reporting this @jadzie and for the sample! This indeed is a bug. I logged #8177 and have a fix coming up.

@jadzie
Copy link

jadzie commented Mar 25, 2020

@jgrandja glad I could help :)

@thammerl
Copy link

Sign In with LinkedIn V2 does not support the OIDC nonce either. I ended up configuring an authorization request customizer as suggested by @jgrandja here.

@requizm
Copy link

requizm commented Dec 28, 2023

OpenID doc says:
The Authorization Server MUST include the nonce Claim in the ID Token if it was sent in the Authentication Request

So it's not a required field for the sender. I wish there was a provider option for disabling nonce. Is it okay If I open a PR for this issue?

@ashwinlimaye
Copy link

ashwinlimaye commented Jan 21, 2024

@thammerl I am building a python flask app, and running into the issue you mentioned here, where my app is faced with a "missing_claim: Missing "nonce" claim" error. Any suggestions on how to resolve? This is the piece of the code, which is on the callback, where this happens:

Auth route

@app.route('/auth')
def auth():
token = None
try:
token = oauth.linkedin.authorize_access_token(client_secret=app.config['OAUTH_LINKEDIN_CLIENT_SECRET'])
# Fetch user info using AuthLib
resp = oauth.linkedin.get('userinfo')

I recognise that this is an out-of-scope question because diff lan and libs, but I'm a newbie and thought it wouldn't hurt to ask

@requizm
Copy link

requizm commented Jan 23, 2024

@ashwinlimaye You shouldn't send nonce field to LinkedIn. Check out your oauth library to have some configuration to change or try to create a hook before sending a request.

@ashwinlimaye
Copy link

ashwinlimaye commented Jan 23, 2024 via email

@Jdban
Copy link

Jdban commented May 20, 2024

Also found some sample code by the LinkedIn team on GitHub

got a link?

@ashwinlimaye
Copy link

ashwinlimaye commented May 21, 2024

Ah, can't seem to find it. But here are some code snippets that work within my app (today), so should be a good pointer for you:

from linkedin_api.clients.auth.client import AuthClient
from linkedin_api.clients.restli.client import RestliClient
# in api function below fill in variables per your code, for context I use this inside a flask app
auth_client = AuthClient(client_id, client_secret, redirect_url=client_redirect_url) 
restli_client = RestliClient()

@app.route('/login', methods=["GET"])
def login():
# some redacted code, not relevant     
return redirect(auth_client.generate_member_auth_url(scopes=["profile openid email"]))

@app.route("/auth", methods=["GET"])
def oauth():
    args = request.args
    auth_code = args.get("code")

    if not auth_code:
        # User declined login or LinkedIn login failed
        # redacted code
    # user logged in successfully
    token_response = auth_client.exchange_auth_code_for_access_token(auth_code)
    access_token = token_response.access_token

#from this point onwards you can use access token to ascertain logged in user, and the variables with info about logged in user as below

user_info_response = restli_client.get(resource_path="/userinfo", access_token=access_token).entity
user_email = user_info_response['email']  # this is the email ID known to linkedin
first_name = user_info_response['given_name']
last_name = user_info_response['family_name']

@jwcarman
Copy link

I am unfortunately running into this issue with the Intuit (Quickbooks) OpenID Connect implementation. They fail to send the nonce parameter if it's included in the authentication request. Sigh. I'll implement the resolver. I just thought I'd add this comment in case someone else is running into this. Thank you for the workaround tip!

@jwcarman
Copy link

jwcarman commented Sep 13, 2024

Okay, I got it working with the help of Baeldung's article here:

https://www.baeldung.com/spring-security-custom-oauth-requests

Here's my customizeAuthorizationRequest method:

private OAuth2AuthorizationRequest customizeAuthorizationRequest(OAuth2AuthorizationRequest req) {
        return OAuth2AuthorizationRequest.from(req)
                .attributes(attrs -> attrs.remove(OidcParameterNames.NONCE))
                .build();
}

@jwcarman
Copy link

jwcarman commented Sep 13, 2024

Alternatively:

@Configuration
public class SecurityConfiguration {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http, ClientRegistrationRepository clientRegistrationRepository) throws Exception {
        http.oauth2Login(login ->
                login.authorizationEndpoint(authzEndpoint -> {
                    final DefaultOAuth2AuthorizationRequestResolver resolver = new DefaultOAuth2AuthorizationRequestResolver(
                            clientRegistrationRepository, OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI);
                    resolver.setAuthorizationRequestCustomizer(req -> req.attributes(attrs -> attrs.remove(OidcParameterNames.NONCE)));
                    authzEndpoint.authorizationRequestResolver(resolver);
                }));
        return http.build();
    }
}

@ginomarckx
Copy link

I am struggling with this as well. The challenge I am having is that I want to disable nonce for some providers (e.g. linkedin), while not for the others (e.g. google).

I see no way of doing this cleanly, and am required to duplicate code to extract the clientRegistrationId from the requestUri.

Does anyone know of a clean way to use the customizer for a specific registrationId?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.