@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 https://github.com/spring-projects/spring-security/issues/4442#issuecomment-561318109
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).
Comment From: jgrandja
@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.
Comment From: hejianchao
@jgrandja It works but not so convenient, For optional parameters like nonce, switches are a more convenient way. Anyway, thanks for your information.
Comment From: jgrandja
@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?
Comment From: hejianchao
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());
}
}
Comment From: jgrandja
@hejianchao Which provider are you using?
Comment From: soarten
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.
Comment From: jgrandja
@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.
Comment From: hejianchao
@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.
Comment From: soarten
Using switches for all sorts of options is far from ideal indeed, this would be a better solution!
Comment From: jadzie
@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.
Comment From: jgrandja
@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.
Comment From: jadzie
@jgrandja ok, will try to do it for tomorrow
Comment From: jadzie
@jgrandja https://github.com/jadzie/login-oidc-customizer-test I hope the readme is descriptive enough :)
Comment From: jgrandja
Thank you for reporting this @jadzie and for the sample! This indeed is a bug. I logged #8177 and have a fix coming up.
Comment From: jadzie
@jgrandja glad I could help :)
Comment From: thammerl
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.
Comment From: requizm
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?
Comment From: ashwinlimaye
@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
Comment From: requizm
@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.
Comment From: ashwinlimaye
Thanks. Actually after some more digging I discovered that LinkedIn have changed a lot of things about how their oauth works. Also found some sample code by the LinkedIn team on GitHub, and now things are working fine. Short version is that there is a large gap between official documentation, sample code that works, and older sample code on various parts of the internet. :-)
On Tue, 23 Jan 2024, 13:00 Menderes, @.***> wrote:
@ashwinlimaye https://github.com/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.
— Reply to this email directly, view it on GitHub https://github.com/spring-projects/spring-security/issues/7696#issuecomment-1906010737, or unsubscribe https://github.com/notifications/unsubscribe-auth/A5HDRE56DY4GPWIZZAUXFZDYP6X7BAVCNFSM4JVB37I2U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TCOJQGYYDCMBXGM3Q . You are receiving this because you were mentioned.Message ID: @.***>
Comment From: Jdban
Also found some sample code by the LinkedIn team on GitHub
got a link?
Comment From: ashwinlimaye
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']
Comment From: jwcarman
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!
Comment From: jwcarman
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();
}
Comment From: jwcarman
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();
}
}
Comment From: ginomarckx
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?