use of oidc.model.User in project OpenConext-oidcng by OpenConext.
the class ResponseAuthenticationConverter method buildUser.
private User buildUser(Assertion assertion, String authenticationRequestID) {
List<AuthnStatement> authnStatements = assertion.getAuthnStatements();
AtomicReference<String> authenticatingAuthority = new AtomicReference<>();
if (!CollectionUtils.isEmpty(authnStatements)) {
authnStatements.stream().map(as -> as.getAuthnContext().getAuthenticatingAuthorities()).flatMap(List::stream).findAny().ifPresent(aa -> authenticatingAuthority.set(aa.getURI()));
}
// need to prevent NullPointer in HashMap merge
Map<String, Object> attributes = userAttributes.stream().filter(ua -> !ua.customMapping).map(ua -> new Object[] { ua.oidc, ua.multiValue ? getAttributeValues(ua.saml, assertion) : getAttributeValue(ua.saml, assertion) }).filter(oo -> oo[1] != null).collect(Collectors.toMap(oo -> (String) oo[0], oo -> oo[1]));
this.addDerivedAttributes(attributes);
AuthenticationRequest authenticationRequest = authenticationRequestRepository.findById(authenticationRequestID).orElseThrow(() -> new IllegalArgumentException("No Authentication Request found for ID: " + authenticationRequestID));
String clientId = authenticationRequest.getClientId();
String nameId = assertion.getSubject().getNameID().getValue();
String eduPersonTargetedId = getAttributeValue("urn:mace:dir:attribute-def:eduPersonTargetedID", assertion);
String collabPersonId = getAttributeValue("urn:mace:surf.nl:attribute-def:internal-collabPersonId", assertion);
String sub;
if (StringUtils.hasText(collabPersonId)) {
sub = nameId;
nameId = collabPersonId;
} else if (StringUtils.hasText(eduPersonTargetedId)) {
sub = eduPersonTargetedId;
} else {
sub = UUID.nameUUIDFromBytes((nameId + "_" + clientId).getBytes()).toString();
}
attributes.put("sub", sub);
List<String> acrClaims = assertion.getAuthnStatements().stream().map(authenticationStatement -> authenticationContextClassReference(authenticationStatement.getAuthnContext().getAuthnContextClassRef())).filter(Optional::isPresent).map(Optional::get).collect(toList());
return new User(sub, nameId, authenticatingAuthority.get(), clientId, attributes, acrClaims);
}
use of oidc.model.User in project OpenConext-oidcng by OpenConext.
the class ResponseAuthenticationConverterTest method login.
@Test
public void login() throws XMLParserException, UnmarshallingException, IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
when(authenticationRequestRepository.findById(anyString())).thenReturn(Optional.of(new AuthenticationRequest("id", new Date(), "clientId", "http://some")));
OidcSamlAuthentication oidcSamlAuthentication = doLogin("saml/authn_response.xml");
User user = oidcSamlAuthentication.getUser();
String sub = user.getSub();
assertEquals("270E4CB4-1C2A-4A96-9AD3-F28C39AD1110", sub);
assertEquals("urn:collab:person:example.com:admin", oidcSamlAuthentication.getName());
assertEquals(3, ((List) user.getAttributes().get("eduperson_affiliation")).size());
}
use of oidc.model.User in project OpenConext-oidcng by OpenConext.
the class AuthorizationEndpoint method doAuthorization.
private ModelAndView doAuthorization(MultiValueMap<String, String> parameters, OidcSamlAuthentication samlAuthentication, HttpServletRequest request, boolean consentRequired) throws ParseException, CertificateException, JOSEException, IOException, BadJOSEException, java.text.ParseException, URISyntaxException {
AuthorizationRequest authenticationRequest = AuthorizationRequest.parse(parameters);
Scope scope = authenticationRequest.getScope();
boolean isOpenIdClient = scope != null && isOpenIDRequest(scope.toStringList());
String clientId = authenticationRequest.getClientID().getValue();
OpenIDClient client = openIDClientRepository.findOptionalByClientId(clientId).orElseThrow(() -> new UnknownClientException(clientId));
MDCContext.mdcContext("action", "Authorize", "rp", client.getClientId());
if (isOpenIdClient) {
AuthenticationRequest oidcAuthenticationRequest = AuthenticationRequest.parse(parameters);
if (oidcAuthenticationRequest.specifiesRequestObject()) {
oidcAuthenticationRequest = JWTRequest.parse(oidcAuthenticationRequest, client);
LOG.debug("/oidc/authorize with JWT 'request'");
}
// swap reference
authenticationRequest = oidcAuthenticationRequest;
}
State state = authenticationRequest.getState();
String redirectURI = validateRedirectionURI(authenticationRequest.getRedirectionURI(), client).getRedirectURI();
List<String> scopes = validateScopes(openIDClientRepository, authenticationRequest.getScope(), client);
ResponseType responseType = validateGrantType(authenticationRequest, client);
User user = samlAuthentication.getUser();
MDCContext.mdcContext(user);
if (scope != null) {
List<String> scopeList = scope.toStringList();
boolean apiScopeRequested = !(scopeList.size() == 0 || (scopeList.size() == 1 && scopeList.contains("openid")));
Set<String> filteredScopes = scopeList.stream().filter(s -> !s.equalsIgnoreCase("openid")).map(String::toLowerCase).collect(toSet());
List<OpenIDClient> resourceServers = openIDClientRepository.findByScopes_NameIn(filteredScopes);
Prompt prompt = authenticationRequest.getPrompt();
boolean consentFromPrompt = prompt != null && prompt.toStringList().contains("consent");
/*
* We prompt for consent when the following conditions are met:
* Consent feature toggle is on
* The RP has requested scope(s) other then openid
* Manage attribute "oidc:consentRequired" is true for the RP or the RP has explicitly asked for consent
* There is at least one ResourceServer that has the requested scope(s) configured in manage
*/
if (consentRequired && apiScopeRequested && (consentFromPrompt || client.isConsentRequired()) && resourceServers.size() > 0) {
LOG.info("Asking for consent for User " + user + " and scopes " + scopes);
return doConsent(parameters, client, filteredScopes, resourceServers);
}
}
// We do not provide SSO as does EB not - up to the identity provider
logout(request);
ResponseMode responseMode = authenticationRequest.impliedResponseMode();
if (responseType.impliesCodeFlow()) {
AuthorizationCode authorizationCode = createAndSaveAuthorizationCode(authenticationRequest, client, user);
LOG.debug(String.format("Returning authorizationCode flow %s %s", ResponseMode.FORM_POST, redirectURI));
if (responseMode.equals(ResponseMode.FORM_POST)) {
Map<String, String> body = new HashMap<>();
body.put("redirect_uri", redirectURI);
body.put("code", authorizationCode.getCode());
if (state != null && StringUtils.hasText(state.getValue())) {
body.put("state", state.getValue());
}
return new ModelAndView("form_post", body);
}
return new ModelAndView(new RedirectView(authorizationRedirect(redirectURI, state, authorizationCode.getCode(), responseMode.equals(ResponseMode.FRAGMENT))));
} else if (responseType.impliesImplicitFlow() || responseType.impliesHybridFlow()) {
if (responseType.impliesImplicitFlow()) {
// User information is encrypted in access token
LOG.debug("Deleting user " + user.getSub());
userRepository.delete(user);
}
Map<String, Object> body = authorizationEndpointResponse(user, client, authenticationRequest, scopes, responseType, state);
LOG.debug(String.format("Returning implicit flow %s %s", ResponseMode.FORM_POST, redirectURI));
if (responseMode.equals(ResponseMode.FORM_POST)) {
body.put("redirect_uri", redirectURI);
return new ModelAndView("form_post", body);
}
if (responseMode.equals(ResponseMode.QUERY)) {
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(redirectURI);
body.forEach(builder::queryParam);
return new ModelAndView(new RedirectView(builder.toUriString()));
}
if (responseMode.equals(ResponseMode.FRAGMENT)) {
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(redirectURI);
String fragment = body.entrySet().stream().map(entry -> String.format("%s=%s", entry.getKey(), entry.getValue())).collect(Collectors.joining("&"));
builder.fragment(fragment);
return new ModelAndView(new RedirectView(builder.toUriString()));
}
throw new IllegalArgumentException("Response mode " + responseMode + " not supported");
}
throw new IllegalArgumentException("Not yet implemented response_type: " + responseType.toString());
}
use of oidc.model.User in project OpenConext-oidcng by OpenConext.
the class TokenEndpoint method handleRefreshCodeGrant.
private ResponseEntity handleRefreshCodeGrant(RefreshTokenGrant refreshTokenGrant, OpenIDClient client) throws java.text.ParseException {
String refreshTokenValue = refreshTokenGrant.getRefreshToken().getValue();
RefreshToken refreshToken;
SignedJWT signedJWT = null;
boolean oldFormat = uuidPattern.matcher(refreshTokenValue).matches();
if (oldFormat) {
// Old refreshToken
refreshToken = refreshTokenRepository.findByInnerValue(refreshTokenValue);
} else {
Optional<SignedJWT> optionalSignedJWT = tokenGenerator.parseAndValidateSignedJWT(refreshTokenValue);
signedJWT = optionalSignedJWT.orElseThrow(() -> new UnauthorizedException("Invalid refresh_token value"));
String jwtId = signedJWT.getJWTClaimsSet().getJWTID();
refreshToken = refreshTokenRepository.findByJwtId(jwtId).orElseThrow(() -> new IllegalArgumentException("RefreshToken not found"));
}
if (!refreshToken.getClientId().equals(client.getClientId())) {
throw new InvalidClientException("Client is not authorized for the refresh token");
}
if (refreshToken.isExpired(Clock.systemDefaultZone())) {
throw new UnauthorizedException("Refresh token expired");
}
// New tokens will be issued
refreshTokenRepository.delete(refreshToken);
// It is possible that the access token is already removed by cron cleanup actions
Optional<AccessToken> accessToken;
if (oldFormat) {
// It is possible that the access token is already removed by cron cleanup actions
accessToken = accessTokenRepository.findOptionalAccessTokenByValue(refreshToken.getAccessTokenValue());
} else {
accessToken = accessTokenRepository.findById(refreshToken.getAccessTokenId());
}
accessToken.ifPresent(accessTokenRepository::delete);
Optional<User> optionalUser;
if (refreshToken.isClientCredentials()) {
optionalUser = Optional.empty();
} else if (oldFormat) {
optionalUser = Optional.of(tokenGenerator.decryptAccessTokenWithEmbeddedUserInfo(refreshToken.getAccessTokenValue()));
} else {
optionalUser = Optional.of(tokenGenerator.decryptAccessTokenWithEmbeddedUserInfo(signedJWT));
}
Map<String, Object> body = tokenEndpointResponse(optionalUser, client, refreshToken.getScopes(), Collections.emptyList(), false, null, optionalUser.map(User::getUpdatedAt), Optional.empty());
return new ResponseEntity<>(body, responseHttpHeaders, HttpStatus.OK);
}
use of oidc.model.User in project OpenConext-oidcng by OpenConext.
the class TokenEndpoint method tokenEndpointResponse.
private Map<String, Object> tokenEndpointResponse(Optional<User> user, OpenIDClient client, List<String> scopes, List<String> idTokenClaims, boolean clientCredentials, String nonce, Optional<Long> authorizationTime, Optional<String> authorizationCodeId) {
Map<String, Object> map = new LinkedHashMap<>();
EncryptedTokenValue encryptedAccessToken = user.map(u -> tokenGenerator.generateAccessTokenWithEmbeddedUserInfo(u, client, scopes)).orElse(tokenGenerator.generateAccessToken(client, scopes));
String sub = user.map(User::getSub).orElse(client.getClientId());
String unspecifiedUrnHash = user.map(u -> KeyGenerator.oneWayHash(u.getUnspecifiedNameId(), this.salt)).orElse(null);
AccessToken accessToken = new AccessToken(encryptedAccessToken.getJwtId(), sub, client.getClientId(), scopes, encryptedAccessToken.getKeyId(), accessTokenValidity(client), !user.isPresent(), authorizationCodeId.orElse(null), unspecifiedUrnHash);
accessToken = accessTokenRepository.insert(accessToken);
map.put("access_token", encryptedAccessToken.getValue());
map.put("token_type", "Bearer");
if (client.getGrants().contains(GrantType.REFRESH_TOKEN.getValue())) {
EncryptedTokenValue encryptedRefreshToken = user.map(u -> tokenGenerator.generateRefreshTokenWithEmbeddedUserInfo(u, client)).orElse(tokenGenerator.generateRefreshToken(client));
String refreshTokenValue = encryptedRefreshToken.getValue();
refreshTokenRepository.insert(new RefreshToken(encryptedRefreshToken.getJwtId(), accessToken, refreshTokenValidity(client)));
map.put("refresh_token", refreshTokenValue);
}
map.put("expires_in", client.getAccessTokenValidity());
if (isOpenIDRequest(scopes) && !clientCredentials) {
TokenValue tokenValue = tokenGenerator.generateIDTokenForTokenEndpoint(user, client, nonce, idTokenClaims, scopes, authorizationTime);
map.put("id_token", tokenValue.getValue());
}
return map;
}
Aggregations