{"record":{"id":"17e751f0d57a9354","repo":"spring-projects/spring-security","slug":"missing-user-info-uri","errorCode":"missing_user_info_uri","errorMessage":"Missing required UserInfo Uri in UserInfoEndpoint for Client Registration: ${registrationId}","messagePattern":"Missing required UserInfo Uri in UserInfoEndpoint for Client Registration: (.+?)","errorType":"error_code","errorClass":"OAuth2AuthenticationException","httpStatus":null,"severity":"error","filePath":"oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DefaultOAuth2UserService.java","lineNumber":178,"sourceCode":"\t\t\t\t\t+ \"as defined in OpenID Connect 1.0: 'https://openid.net/specs/openid-connect-core-1_0.html#UserInfo'\";\n\t\t\tOAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE, errorMessage, null);\n\t\t\tthrow new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), ex);\n\t\t}\n\t\tcatch (RestClientException ex) {\n\t\t\tOAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE,\n\t\t\t\t\t\"An error occurred while attempting to retrieve the UserInfo Resource: \" + ex.getMessage(), null);\n\t\t\tthrow new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), ex);\n\t\t}\n\t}\n\n\tprivate String getUserNameAttributeName(OAuth2UserRequest userRequest) {\n\t\tif (!StringUtils\n\t\t\t.hasText(userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri())) {\n\t\t\tOAuth2Error oauth2Error = new OAuth2Error(MISSING_USER_INFO_URI_ERROR_CODE,\n\t\t\t\t\t\"Missing required UserInfo Uri in UserInfoEndpoint for Client Registration: \"\n\t\t\t\t\t\t\t+ userRequest.getClientRegistration().getRegistrationId(),\n\t\t\t\t\tnull);\n\t\t\tthrow new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());\n\t\t}\n\t\tString userNameAttributeName = userRequest.getClientRegistration()\n\t\t\t.getProviderDetails()\n\t\t\t.getUserInfoEndpoint()\n\t\t\t.getUserNameAttributeName();\n\t\tif (!StringUtils.hasText(userNameAttributeName)) {\n\t\t\tOAuth2Error oauth2Error = new OAuth2Error(MISSING_USER_NAME_ATTRIBUTE_ERROR_CODE,\n\t\t\t\t\t\"Missing required \\\"user name\\\" attribute name in UserInfoEndpoint for Client Registration: \"\n\t\t\t\t\t\t\t+ userRequest.getClientRegistration().getRegistrationId(),\n\t\t\t\t\tnull);\n\t\t\tthrow new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());\n\t\t}\n\t\treturn userNameAttributeName;\n\t}\n\n\tprivate Collection<GrantedAuthority> getAuthorities(OAuth2AccessToken token, Map<String, Object> attributes,\n\t\t\tString userNameAttributeName) {\n\t\tCollection<GrantedAuthority> authorities = new LinkedHashSet<>();","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/userinfo/DefaultOAuth2UserService.java#L160-L196","documentation":"DefaultOAuth2UserService.getUserNameAttributeName validates that the ClientRegistration's UserInfoEndpoint has a non-empty uri before it can fetch claims. When user-info-uri is blank, it throws OAuth2AuthenticationException with code 'missing_user_info_uri'. This happens because the user-info flow (as opposed to the JWT-based id-token flow) depends entirely on the UserInfo endpoint.","triggerScenarios":"ClientRegistration built via ClientRegistrations/ClientRegistration.withRegistrationId(...) without user-info-uri (or with an empty string), and the app takes the user-info path (e.g. OIDC provider that does not put email claim in id_token, or OAuth2 login for a non-OIDC provider), causing loadUser to call getUserNameAttributeName.","commonSituations":"Plain OAuth2 providers (GitHub-style manual registration) where the developer forgot user-info-uri; dynamic provider config missing userinfo_endpoint; typos like userNameAttributeName set but uri left blank; upgrading and switching from id-token-only config to user-info config.","solutions":["Add user-info-uri to the provider details (spring.security.oauth2.client.provider.<id>.user-info-uri or programmatically userInfoEndpoint().uri(...)).","If the provider is OIDC-compliant, use issuer-uri based registration so userinfo_endpoint is discovered automatically.","Alternatively avoid the UserInfo call by relying on id_token claims (ensure the required claims are present and userNameAttributeName maps to an id_token claim).","Validate the ClientRegistration at startup (fail fast in a @Configuration) so the missing uri is caught before a user tries to log in."],"exampleFix":"// before\nspring.security.oauth2.client.registration.myclient.client-id=id\nspring.security.oauth2.client.registration.myclient.client-secret=secret\n# no provider user-info-uri\n\n// after\nspring.security.oauth2.client.registration.myclient.provider=myprovider\nspring.security.oauth2.client.provider.myprovider.authorization-uri=https://idp.example.com/authorize\nspring.security.oauth2.client.provider.myprovider.token-uri=https://idp.example.com/token\nspring.security.oauth2.client.provider.myprovider.user-info-uri=https://idp.example.com/userinfo\nspring.security.oauth2.client.provider.myprovider.user-name-attribute=sub","handlingStrategy":"validation","validationCode":"ClientRegistration reg = repository.findByRegistrationId(\"myclient\");\nif (reg == null || !StringUtils.hasText(reg.getProviderDetails().getUserInfoEndpoint().getUri())) {\n    throw new IllegalStateException(\"user-info-uri must be configured for myclient\");\n}","typeGuard":null,"tryCatchPattern":"catch (OAuth2AuthenticationException ex) {\n    if (\"missing_user_info_uri\".equals(ex.getError().getErrorCode())) {\n        // config bug: fail startup or redirect to an error page with guidance\n    }\n}","preventionTips":["Validate all ClientRegistrations at startup (fail-fast @PostConstruct check)","Prefer issuer-uri discovery so userinfo_endpoint is filled automatically","Keep provider config in one reviewed place (application.yml) rather than ad-hoc code","Add an integration test that performs a login against a stub IdP"],"tags":["oauth2","oidc","configuration","userinfo","spring-security"],"backgroundTag":"missing-required-config-field","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}