private boolean shouldRetrieveUserInfo(OidcUserRequest userRequest) { // Auto-disabled if UserInfo Endpoint URI is not provided if (StringUtils.isEmpty(userRequest.getClientRegistration().getProviderDetails() .getUserInfoEndpoint().getUri())) { return false; } // The Claims requested by the profile, email, address, and phone scope values // are returned from the UserInfo Endpoint (as described in Section 5.3.2), // when a response_type value is used that results in an Access Token being issued. // However, when no Access Token is issued, which is the case for the response_type=id_token, // the resulting Claims are returned in the ID Token. // The Authorization Code Grant Flow, which is response_type=code, results in an Access Token being issued. if (AuthorizationGrantType.AUTHORIZATION_CODE.equals( userRequest.getClientRegistration().getAuthorizationGrantType())) { // Return true if there is at least one match between the authorized scope(s) and UserInfo scope(s) return CollectionUtils.containsAny(userRequest.getAccessToken().getScopes(), this.userInfoScopes); } return false; }
@Test public void constructorWhenAllParametersProvidedAndValidThenCreated() { OidcUserRequest userRequest = new OidcUserRequest( this.clientRegistration, this.accessToken, this.idToken, this.additionalParameters); assertThat(userRequest.getClientRegistration()).isEqualTo(this.clientRegistration); assertThat(userRequest.getAccessToken()).isEqualTo(this.accessToken); assertThat(userRequest.getIdToken()).isEqualTo(this.idToken); assertThat(userRequest.getAdditionalParameters()).containsAllEntriesOf(this.additionalParameters); } }
@Override public Mono<OidcUser> loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException { Assert.notNull(userRequest, "userRequest cannot be null"); return getUserInfo(userRequest) .map(userInfo -> new OidcUserAuthority(userRequest.getIdToken(), userInfo)) .defaultIfEmpty(new OidcUserAuthority(userRequest.getIdToken(), null)) .map(authority -> { OidcUserInfo userInfo = authority.getUserInfo(); Set<GrantedAuthority> authorities = new HashSet<>(); authorities.add(authority); String userNameAttributeName = userRequest.getClientRegistration() .getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName(); if (StringUtils.hasText(userNameAttributeName)) { return new DefaultOidcUser(authorities, userRequest.getIdToken(), userInfo, userNameAttributeName); } else { return new DefaultOidcUser(authorities, userRequest.getIdToken(), userInfo); } }); }
ClientRegistration clientRegistration = userRequest.getClientRegistration(); if (StringUtils.isEmpty(clientRegistration.getProviderDetails() .getUserInfoEndpoint().getUri())) { .containsAny(userRequest.getAccessToken().getScopes(), userRequest.getClientRegistration().getScopes());
String userNameAttributeName = userRequest.getClientRegistration() .getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName(); if (StringUtils.hasText(userNameAttributeName)) {
private OidcClient getOidcClient(OidcUserRequest userRequest) { String registrationId = userRequest.getClientRegistration().getRegistrationId(); OidcClient oidcClient = dataService.findOneById(OidcClientMetadata.OIDC_CLIENT, registrationId, OidcClient.class); if (oidcClient == null) { throw new UnknownEntityException(OidcClientMetadata.OIDC_CLIENT, registrationId); } return oidcClient; } }
/** package-private for testability */ private String getUserNameAttributeName(OidcUserRequest userRequest) { return userRequest .getClientRegistration() .getProviderDetails() .getUserInfoEndpoint() .getUserNameAttributeName(); } }
String clientId = userRequest.getClientRegistration().getClientId();
private boolean shouldRetrieveUserInfo(OidcUserRequest userRequest) { // Auto-disabled if UserInfo Endpoint URI is not provided if (StringUtils.isEmpty(userRequest.getClientRegistration().getProviderDetails() .getUserInfoEndpoint().getUri())) { return false; } // The Claims requested by the profile, email, address, and phone scope values // are returned from the UserInfo Endpoint (as described in Section 5.3.2), // when a response_type value is used that results in an Access Token being issued. // However, when no Access Token is issued, which is the case for the response_type=id_token, // the resulting Claims are returned in the ID Token. // The Authorization Code Grant Flow, which is response_type=code, results in an Access Token being issued. if (AuthorizationGrantType.AUTHORIZATION_CODE.equals( userRequest.getClientRegistration().getAuthorizationGrantType())) { // Return true if there is at least one match between the authorized scope(s) and UserInfo scope(s) return CollectionUtils.containsAny(userRequest.getAccessToken().getScopes(), this.userInfoScopes); } return false; }
private Optional<User> getUser(OidcUser oidcUser, OidcUserRequest userRequest) { OidcUserMapping oidcUserMapping = dataService .query(OIDC_USER_MAPPING, OidcUserMapping.class) .eq(OIDC_CLIENT, userRequest.getClientRegistration().getRegistrationId()) .and() .eq(OIDC_USERNAME, oidcUser.getSubject()) .findOne(); return oidcUserMapping != null ? Optional.of(oidcUserMapping.getUser()) : Optional.empty(); }
@Override public Mono<OidcUser> loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException { Assert.notNull(userRequest, "userRequest cannot be null"); return getUserInfo(userRequest) .map(userInfo -> new OidcUserAuthority(userRequest.getIdToken(), userInfo)) .defaultIfEmpty(new OidcUserAuthority(userRequest.getIdToken(), null)) .map(authority -> { OidcUserInfo userInfo = authority.getUserInfo(); Set<GrantedAuthority> authorities = new HashSet<>(); authorities.add(authority); String userNameAttributeName = userRequest.getClientRegistration() .getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName(); if (StringUtils.hasText(userNameAttributeName)) { return new DefaultOidcUser(authorities, userRequest.getIdToken(), userInfo, userNameAttributeName); } else { return new DefaultOidcUser(authorities, userRequest.getIdToken(), userInfo); } }); }
@Override public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException { OidcUser user = super.loadUser(userRequest); // Only post process requests from the "Okta" reg if (!"Okta".equals(userRequest.getClientRegistration().getClientName())) { return user; } // start with authorities from super Set<GrantedAuthority> authorities = new HashSet<>(user.getAuthorities()); // add 'SCOPE_' authorities authorities.addAll(TokenUtil.tokenScopesToAuthorities(userRequest.getAccessToken())); // add any authorities extracted from the 'group' claim authorities.addAll(TokenUtil.tokenClaimsToAuthorities(user.getAttributes(), groupClaim)); String userNameAttributeName = userRequest.getClientRegistration() .getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName(); return StringUtils.hasText(userNameAttributeName) ? new DefaultOidcUser(authorities, user.getIdToken(), user.getUserInfo(), userNameAttributeName) : new DefaultOidcUser(authorities, user.getIdToken(), user.getUserInfo()); } }
ClientRegistration clientRegistration = userRequest.getClientRegistration(); if (StringUtils.isEmpty(clientRegistration.getProviderDetails() .getUserInfoEndpoint().getUri())) { .containsAny(userRequest.getAccessToken().getScopes(), userRequest.getClientRegistration().getScopes());
@Override public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException { OidcUser oidcUser = super.loadUser(userRequest); LemonPrincipal principal = oauth2UserService.buildPrincipal(oidcUser, userRequest.getClientRegistration().getRegistrationId()); principal.setClaims(oidcUser.getClaims()); principal.setIdToken(oidcUser.getIdToken()); principal.setUserInfo(oidcUser.getUserInfo()); return principal; } }
String userNameAttributeName = userRequest.getClientRegistration() .getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName(); if (StringUtils.hasText(userNameAttributeName)) {
private User createUserMapping(OidcUser oidcUser, OidcUserRequest userRequest) { User user = dataService .query(UserMetaData.USER, User.class) .eq(UserMetaData.EMAIL, oidcUser.getEmail()) .findOne(); if (user == null) { user = createUser(oidcUser); } OidcClient oidcClient = getOidcClient(userRequest); OidcUserMapping oidcUserMapping = oidcUserMappingFactory.create(); oidcUserMapping.setLabel( userRequest.getClientRegistration().getRegistrationId() + ':' + oidcUser.getSubject()); oidcUserMapping.setOidcClient(oidcClient); oidcUserMapping.setOidcUsername(oidcUser.getSubject()); oidcUserMapping.setUser(user); dataService.add(OIDC_USER_MAPPING, oidcUserMapping); return user; }
@Override public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException { final OidcUserService delegate = new OidcUserService(); // Delegate to the default implementation for loading a user OidcUser oidcUser = delegate.loadUser(userRequest); final OidcIdToken idToken = userRequest.getIdToken(); final String graphApiToken; final Set<GrantedAuthority> mappedAuthorities; try { // https://github.com/MicrosoftDocs/azure-docs/issues/8121#issuecomment-387090099 // In AAD App Registration configure oauth2AllowImplicitFlow to true final ClientRegistration registration = userRequest.getClientRegistration(); final ClientCredential credential = new ClientCredential(registration.getClientId(), registration.getClientSecret()); final AzureADGraphClient graphClient = new AzureADGraphClient(credential, aadAuthProps, serviceEndpointsProps); graphApiToken = graphClient.acquireTokenForGraphApi(idToken.getTokenValue(), aadAuthProps.getTenantId()).getAccessToken(); mappedAuthorities = graphClient.getGrantedAuthorities(graphApiToken); } catch (MalformedURLException e) { throw wrapException(INVALID_REQUEST, "Failed to acquire token for Graph API.", null, e); } catch (ServiceUnavailableException | InterruptedException | ExecutionException e) { throw wrapException(SERVER_ERROR, "Failed to acquire token for Graph API.", null, e); } catch (IOException e) { throw wrapException(SERVER_ERROR, "Failed to map group to authorities.", null, e); } // Create a copy of oidcUser but use the mappedAuthorities instead oidcUser = new DefaultOidcUser(mappedAuthorities, oidcUser.getIdToken(), getUserNameAttrName(userRequest)); return oidcUser; }
@Override public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException { final OidcUserService delegate = new OidcUserService(); // Delegate to the default implementation for loading a user OidcUser oidcUser = delegate.loadUser(userRequest); final OidcIdToken idToken = userRequest.getIdToken(); final String graphApiToken; final Set<GrantedAuthority> mappedAuthorities; try { // https://github.com/MicrosoftDocs/azure-docs/issues/8121#issuecomment-387090099 // In AAD App Registration configure oauth2AllowImplicitFlow to true final ClientRegistration registration = userRequest.getClientRegistration(); final ClientCredential credential = new ClientCredential(registration.getClientId(), registration.getClientSecret()); final AzureADGraphClient graphClient = new AzureADGraphClient(credential, aadAuthProps, serviceEndpointsProps); graphApiToken = graphClient.acquireTokenForGraphApi(idToken.getTokenValue(), aadAuthProps.getTenantId()).getAccessToken(); mappedAuthorities = graphClient.getGrantedAuthorities(graphApiToken); } catch (MalformedURLException e) { throw wrapException(INVALID_REQUEST, "Failed to acquire token for Graph API.", null, e); } catch (ServiceUnavailableException | InterruptedException | ExecutionException e) { throw wrapException(SERVER_ERROR, "Failed to acquire token for Graph API.", null, e); } catch (IOException e) { throw wrapException(SERVER_ERROR, "Failed to map group to authorities.", null, e); } // Create a copy of oidcUser but use the mappedAuthorities instead oidcUser = new DefaultOidcUser(mappedAuthorities, oidcUser.getIdToken(), getUserNameAttrName(userRequest)); return oidcUser; }