Created token service for OIDC special tokens; removed creation of id tokens and registration_access_tokens to the new service.
parent
26a7d0b8a8
commit
47d304851d
|
@ -0,0 +1,59 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright 2013 The MITRE Corporation
|
||||||
|
* and the MIT Kerberos and Internet Trust Consortium
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
******************************************************************************/
|
||||||
|
package org.mitre.openid.connect.service;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||||
|
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
||||||
|
import org.springframework.security.oauth2.provider.OAuth2Request;
|
||||||
|
|
||||||
|
import com.nimbusds.jose.JWSAlgorithm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service to create specialty OpenID Connect tokens.
|
||||||
|
*
|
||||||
|
* @author Amanda Anganes
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface OIDCTokenService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an id token with the information provided.
|
||||||
|
*
|
||||||
|
* @param client
|
||||||
|
* @param request
|
||||||
|
* @param issueTime
|
||||||
|
* @param sub
|
||||||
|
* @param signingAlg
|
||||||
|
* @param accessToken
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public OAuth2AccessTokenEntity createIdToken(
|
||||||
|
ClientDetailsEntity client, OAuth2Request request, Date issueTime,
|
||||||
|
String sub, JWSAlgorithm signingAlg,
|
||||||
|
OAuth2AccessTokenEntity accessToken);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a registration access token for the given client.
|
||||||
|
*
|
||||||
|
* @param client
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public OAuth2AccessTokenEntity createRegistrationAccessToken(ClientDetailsEntity client);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,214 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright 2013 The MITRE Corporation
|
||||||
|
* and the MIT Kerberos and Internet Trust Consortium
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
******************************************************************************/
|
||||||
|
package org.mitre.openid.connect.service.impl;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
|
||||||
|
import org.mitre.oauth2.model.AuthenticationHolderEntity;
|
||||||
|
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||||
|
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
||||||
|
import org.mitre.oauth2.repository.AuthenticationHolderRepository;
|
||||||
|
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
|
||||||
|
import org.mitre.openid.connect.service.OIDCTokenService;
|
||||||
|
import org.mitre.openid.connect.util.IdTokenHashUtils;
|
||||||
|
import org.mitre.openid.connect.web.AuthenticationTimeStamper;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.oauth2.common.util.OAuth2Utils;
|
||||||
|
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||||
|
import org.springframework.security.oauth2.provider.OAuth2Request;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.nimbusds.jose.JWSAlgorithm;
|
||||||
|
import com.nimbusds.jose.JWSHeader;
|
||||||
|
import com.nimbusds.jose.util.Base64URL;
|
||||||
|
import com.nimbusds.jwt.JWTClaimsSet;
|
||||||
|
import com.nimbusds.jwt.SignedJWT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of service to create specialty OpenID Connect tokens.
|
||||||
|
*
|
||||||
|
* @author Amanda Anganes
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class DefaultOIDCTokenService implements OIDCTokenService {
|
||||||
|
|
||||||
|
Logger logger = LoggerFactory.getLogger(DefaultOIDCTokenService.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtSigningAndValidationService jwtService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthenticationHolderRepository authenticationHolderRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConfigurationPropertiesBean configBean;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OAuth2AccessTokenEntity createIdToken(ClientDetailsEntity client, OAuth2Request request, Date issueTime, String sub, JWSAlgorithm signingAlg, OAuth2AccessTokenEntity accessToken) {
|
||||||
|
|
||||||
|
OAuth2AccessTokenEntity idTokenEntity = new OAuth2AccessTokenEntity();
|
||||||
|
JWTClaimsSet idClaims = new JWTClaimsSet();
|
||||||
|
|
||||||
|
if (request.getExtensions().containsKey(AuthenticationTimeStamper.AUTH_TIMESTAMP)) {
|
||||||
|
Date authTime = (Date) request.getExtensions().get(AuthenticationTimeStamper.AUTH_TIMESTAMP);
|
||||||
|
idClaims.setClaim("auth_time", authTime.getTime() / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
idClaims.setIssueTime(issueTime);
|
||||||
|
|
||||||
|
if (client.getIdTokenValiditySeconds() != null) {
|
||||||
|
Date expiration = new Date(System.currentTimeMillis() + (client.getIdTokenValiditySeconds() * 1000L));
|
||||||
|
idClaims.setExpirationTime(expiration);
|
||||||
|
idTokenEntity.setExpiration(expiration);
|
||||||
|
}
|
||||||
|
|
||||||
|
idClaims.setIssuer(configBean.getIssuer());
|
||||||
|
idClaims.setSubject(sub);
|
||||||
|
idClaims.setAudience(Lists.newArrayList(client.getClientId()));
|
||||||
|
|
||||||
|
String nonce = (String)request.getExtensions().get("nonce");
|
||||||
|
if (!Strings.isNullOrEmpty(nonce)) {
|
||||||
|
idClaims.setCustomClaim("nonce", nonce);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this ought to be getResponseType; issue #482
|
||||||
|
String responseType = request.getRequestParameters().get("response_type");
|
||||||
|
|
||||||
|
Set<String> responseTypes = OAuth2Utils.parseParameterList(responseType);
|
||||||
|
if (responseTypes.contains("token")) {
|
||||||
|
// calculate the token hash
|
||||||
|
Base64URL at_hash = IdTokenHashUtils.getAccessTokenHash(signingAlg, accessToken);
|
||||||
|
idClaims.setClaim("at_hash", at_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
SignedJWT idToken = new SignedJWT(new JWSHeader(signingAlg), idClaims);
|
||||||
|
|
||||||
|
jwtService.signJwt(idToken);
|
||||||
|
|
||||||
|
idTokenEntity.setJwt(idToken);
|
||||||
|
|
||||||
|
idTokenEntity.setAuthenticationHolder(accessToken.getAuthenticationHolder());
|
||||||
|
|
||||||
|
// create a scope set with just the special "id-token" scope
|
||||||
|
//Set<String> idScopes = new HashSet<String>(token.getScope()); // this would copy the original token's scopes in, we don't really want that
|
||||||
|
Set<String> idScopes = Sets.newHashSet(OAuth2AccessTokenEntity.ID_TOKEN_SCOPE);
|
||||||
|
idTokenEntity.setScope(idScopes);
|
||||||
|
|
||||||
|
idTokenEntity.setClient(accessToken.getClient());
|
||||||
|
|
||||||
|
return idTokenEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param client
|
||||||
|
* @return
|
||||||
|
* @throws AuthenticationException
|
||||||
|
*/
|
||||||
|
public OAuth2AccessTokenEntity createRegistrationAccessToken(ClientDetailsEntity client) {
|
||||||
|
|
||||||
|
Map<String, String> authorizationParameters = Maps.newHashMap();
|
||||||
|
OAuth2Request clientAuth = new OAuth2Request(authorizationParameters, client.getClientId(),
|
||||||
|
Sets.newHashSet(new SimpleGrantedAuthority("ROLE_CLIENT")), true,
|
||||||
|
Sets.newHashSet(OAuth2AccessTokenEntity.REGISTRATION_TOKEN_SCOPE), null, null, null);
|
||||||
|
OAuth2Authentication authentication = new OAuth2Authentication(clientAuth, null);
|
||||||
|
|
||||||
|
OAuth2AccessTokenEntity token = new OAuth2AccessTokenEntity();
|
||||||
|
token.setClient(client);
|
||||||
|
token.setScope(Sets.newHashSet(OAuth2AccessTokenEntity.REGISTRATION_TOKEN_SCOPE));
|
||||||
|
|
||||||
|
AuthenticationHolderEntity authHolder = new AuthenticationHolderEntity();
|
||||||
|
authHolder.setAuthentication(authentication);
|
||||||
|
authHolder = authenticationHolderRepository.save(authHolder);
|
||||||
|
token.setAuthenticationHolder(authHolder);
|
||||||
|
|
||||||
|
JWTClaimsSet claims = new JWTClaimsSet();
|
||||||
|
|
||||||
|
claims.setAudience(Lists.newArrayList(client.getClientId()));
|
||||||
|
claims.setIssuer(configBean.getIssuer());
|
||||||
|
claims.setIssueTime(new Date());
|
||||||
|
claims.setExpirationTime(token.getExpiration());
|
||||||
|
claims.setJWTID(UUID.randomUUID().toString()); // set a random NONCE in the middle of it
|
||||||
|
|
||||||
|
// TODO: use client's default signing algorithm
|
||||||
|
JWSAlgorithm signingAlg = jwtService.getDefaultSigningAlgorithm();
|
||||||
|
SignedJWT signed = new SignedJWT(new JWSHeader(signingAlg), claims);
|
||||||
|
|
||||||
|
jwtService.signJwt(signed);
|
||||||
|
|
||||||
|
token.setJwt(signed);
|
||||||
|
|
||||||
|
return token;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the configBean
|
||||||
|
*/
|
||||||
|
public ConfigurationPropertiesBean getConfigBean() {
|
||||||
|
return configBean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param configBean the configBean to set
|
||||||
|
*/
|
||||||
|
public void setConfigBean(ConfigurationPropertiesBean configBean) {
|
||||||
|
this.configBean = configBean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the jwtService
|
||||||
|
*/
|
||||||
|
public JwtSigningAndValidationService getJwtService() {
|
||||||
|
return jwtService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param jwtService the jwtService to set
|
||||||
|
*/
|
||||||
|
public void setJwtService(JwtSigningAndValidationService jwtService) {
|
||||||
|
this.jwtService = jwtService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the authenticationHolderRepository
|
||||||
|
*/
|
||||||
|
public AuthenticationHolderRepository getAuthenticationHolderRepository() {
|
||||||
|
return authenticationHolderRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param authenticationHolderRepository the authenticationHolderRepository to set
|
||||||
|
*/
|
||||||
|
public void setAuthenticationHolderRepository(
|
||||||
|
AuthenticationHolderRepository authenticationHolderRepository) {
|
||||||
|
this.authenticationHolderRepository = authenticationHolderRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,7 +17,6 @@
|
||||||
package org.mitre.openid.connect.token;
|
package org.mitre.openid.connect.token;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
|
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
|
||||||
|
@ -27,25 +26,20 @@ import org.mitre.oauth2.service.ClientDetailsEntityService;
|
||||||
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
|
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
|
||||||
import org.mitre.openid.connect.model.UserInfo;
|
import org.mitre.openid.connect.model.UserInfo;
|
||||||
import org.mitre.openid.connect.service.ApprovedSiteService;
|
import org.mitre.openid.connect.service.ApprovedSiteService;
|
||||||
|
import org.mitre.openid.connect.service.OIDCTokenService;
|
||||||
import org.mitre.openid.connect.service.UserInfoService;
|
import org.mitre.openid.connect.service.UserInfoService;
|
||||||
import org.mitre.openid.connect.util.IdTokenHashUtils;
|
|
||||||
import org.mitre.openid.connect.web.AuthenticationTimeStamper;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||||
import org.springframework.security.oauth2.common.util.OAuth2Utils;
|
|
||||||
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||||
import org.springframework.security.oauth2.provider.OAuth2Request;
|
import org.springframework.security.oauth2.provider.OAuth2Request;
|
||||||
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
|
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.nimbusds.jose.JWSAlgorithm;
|
import com.nimbusds.jose.JWSAlgorithm;
|
||||||
import com.nimbusds.jose.JWSHeader;
|
import com.nimbusds.jose.JWSHeader;
|
||||||
import com.nimbusds.jose.util.Base64URL;
|
|
||||||
import com.nimbusds.jwt.JWTClaimsSet;
|
import com.nimbusds.jwt.JWTClaimsSet;
|
||||||
import com.nimbusds.jwt.SignedJWT;
|
import com.nimbusds.jwt.SignedJWT;
|
||||||
|
|
||||||
|
@ -69,6 +63,9 @@ public class ConnectTokenEnhancer implements TokenEnhancer {
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserInfoService userInfoService;
|
private UserInfoService userInfoService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OIDCTokenService connectTokenService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
|
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
|
||||||
|
|
||||||
|
@ -109,64 +106,12 @@ public class ConnectTokenEnhancer implements TokenEnhancer {
|
||||||
*/
|
*/
|
||||||
if (originalAuthRequest.getScope().contains("openid")) {
|
if (originalAuthRequest.getScope().contains("openid")) {
|
||||||
|
|
||||||
// TODO: maybe id tokens need a service layer
|
|
||||||
|
|
||||||
String username = authentication.getName();
|
String username = authentication.getName();
|
||||||
UserInfo userInfo = userInfoService.getByUsernameAndClientId(username, clientId);
|
UserInfo userInfo = userInfoService.getByUsernameAndClientId(username, clientId);
|
||||||
|
|
||||||
OAuth2AccessTokenEntity idTokenEntity = new OAuth2AccessTokenEntity();
|
OAuth2AccessTokenEntity idTokenEntity = connectTokenService.createIdToken(client,
|
||||||
|
originalAuthRequest, (java.util.Date) claims.getIssueTime(),
|
||||||
// FIXME: extend the "claims" section for id tokens
|
userInfo.getSub(), signingAlg, token);
|
||||||
JWTClaimsSet idClaims = new JWTClaimsSet();
|
|
||||||
|
|
||||||
|
|
||||||
if (authentication.getOAuth2Request().getExtensions().containsKey(AuthenticationTimeStamper.AUTH_TIMESTAMP)) {
|
|
||||||
Date authTime = (Date) authentication.getOAuth2Request().getExtensions().get(AuthenticationTimeStamper.AUTH_TIMESTAMP);
|
|
||||||
idClaims.setClaim("auth_time", authTime.getTime() / 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
idClaims.setIssueTime(claims.getIssueTime());
|
|
||||||
|
|
||||||
if (client.getIdTokenValiditySeconds() != null) {
|
|
||||||
Date expiration = new Date(System.currentTimeMillis() + (client.getIdTokenValiditySeconds() * 1000L));
|
|
||||||
idClaims.setExpirationTime(expiration);
|
|
||||||
idTokenEntity.setExpiration(expiration);
|
|
||||||
}
|
|
||||||
|
|
||||||
idClaims.setIssuer(configBean.getIssuer());
|
|
||||||
idClaims.setSubject(userInfo.getSub());
|
|
||||||
idClaims.setAudience(Lists.newArrayList(clientId));
|
|
||||||
|
|
||||||
String nonce = (String)originalAuthRequest.getExtensions().get("nonce");
|
|
||||||
if (!Strings.isNullOrEmpty(nonce)) {
|
|
||||||
idClaims.setCustomClaim("nonce", nonce);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: this ought to be getResponseType; issue #482
|
|
||||||
String responseType = authentication.getOAuth2Request().getRequestParameters().get("response_type");
|
|
||||||
|
|
||||||
Set<String> responseTypes = OAuth2Utils.parseParameterList(responseType);
|
|
||||||
if (responseTypes.contains("token")) {
|
|
||||||
// calculate the token hash
|
|
||||||
Base64URL at_hash = IdTokenHashUtils.getAccessTokenHash(signingAlg, token);
|
|
||||||
//TODO: What should happen if the hash cannot be calculated?
|
|
||||||
idClaims.setClaim("at_hash", at_hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
SignedJWT idToken = new SignedJWT(new JWSHeader(signingAlg), idClaims);
|
|
||||||
|
|
||||||
jwtService.signJwt(idToken);
|
|
||||||
|
|
||||||
idTokenEntity.setJwt(idToken);
|
|
||||||
|
|
||||||
idTokenEntity.setAuthenticationHolder(token.getAuthenticationHolder());
|
|
||||||
|
|
||||||
// create a scope set with just the special "id-token" scope
|
|
||||||
//Set<String> idScopes = new HashSet<String>(token.getScope()); // this would copy the original token's scopes in, we don't really want that
|
|
||||||
Set<String> idScopes = Sets.newHashSet(OAuth2AccessTokenEntity.ID_TOKEN_SCOPE);
|
|
||||||
idTokenEntity.setScope(idScopes);
|
|
||||||
|
|
||||||
idTokenEntity.setClient(token.getClient());
|
|
||||||
|
|
||||||
// attach the id token to the parent access token
|
// attach the id token to the parent access token
|
||||||
token.setIdToken(idTokenEntity);
|
token.setIdToken(idTokenEntity);
|
||||||
|
|
|
@ -16,34 +16,27 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.mitre.openid.connect.web;
|
package org.mitre.openid.connect.web;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
|
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
|
||||||
import org.mitre.oauth2.model.AuthenticationHolderEntity;
|
|
||||||
import org.mitre.oauth2.model.ClientDetailsEntity;
|
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||||
import org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod;
|
import org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod;
|
||||||
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
||||||
import org.mitre.oauth2.model.RegisteredClient;
|
import org.mitre.oauth2.model.RegisteredClient;
|
||||||
import org.mitre.oauth2.model.SystemScope;
|
import org.mitre.oauth2.model.SystemScope;
|
||||||
import org.mitre.oauth2.repository.AuthenticationHolderRepository;
|
|
||||||
import org.mitre.oauth2.service.ClientDetailsEntityService;
|
import org.mitre.oauth2.service.ClientDetailsEntityService;
|
||||||
import org.mitre.oauth2.service.OAuth2TokenEntityService;
|
import org.mitre.oauth2.service.OAuth2TokenEntityService;
|
||||||
import org.mitre.oauth2.service.SystemScopeService;
|
import org.mitre.oauth2.service.SystemScopeService;
|
||||||
import org.mitre.openid.connect.ClientDetailsEntityJsonProcessor;
|
import org.mitre.openid.connect.ClientDetailsEntityJsonProcessor;
|
||||||
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
|
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
|
||||||
|
import org.mitre.openid.connect.service.OIDCTokenService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||||
import org.springframework.security.oauth2.provider.OAuth2Request;
|
|
||||||
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
|
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
|
@ -52,13 +45,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.nimbusds.jose.JWSAlgorithm;
|
|
||||||
import com.nimbusds.jose.JWSHeader;
|
|
||||||
import com.nimbusds.jwt.JWTClaimsSet;
|
|
||||||
import com.nimbusds.jwt.SignedJWT;
|
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@RequestMapping(value = "register")
|
@RequestMapping(value = "register")
|
||||||
|
@ -73,18 +60,15 @@ public class ClientDynamicRegistrationEndpoint {
|
||||||
@Autowired
|
@Autowired
|
||||||
private JwtSigningAndValidationService jwtService;
|
private JwtSigningAndValidationService jwtService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ConfigurationPropertiesBean configBean;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private AuthenticationHolderRepository authenticationHolderRepository;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SystemScopeService scopeService;
|
private SystemScopeService scopeService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ConfigurationPropertiesBean config;
|
private ConfigurationPropertiesBean config;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OIDCTokenService connectTokenService;
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(ClientDynamicRegistrationEndpoint.class);
|
private static Logger logger = LoggerFactory.getLogger(ClientDynamicRegistrationEndpoint.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -170,7 +154,8 @@ public class ClientDynamicRegistrationEndpoint {
|
||||||
ClientDetailsEntity savedClient = clientService.saveNewClient(newClient);
|
ClientDetailsEntity savedClient = clientService.saveNewClient(newClient);
|
||||||
|
|
||||||
// generate the registration access token
|
// generate the registration access token
|
||||||
OAuth2AccessTokenEntity token = createRegistrationAccessToken(savedClient);
|
OAuth2AccessTokenEntity token = connectTokenService.createRegistrationAccessToken(savedClient);
|
||||||
|
tokenService.saveAccessToken(token);
|
||||||
|
|
||||||
// send it all out to the view
|
// send it all out to the view
|
||||||
|
|
||||||
|
@ -345,50 +330,4 @@ public class ClientDynamicRegistrationEndpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param client
|
|
||||||
* @return
|
|
||||||
* @throws AuthenticationException
|
|
||||||
*/
|
|
||||||
private OAuth2AccessTokenEntity createRegistrationAccessToken(ClientDetailsEntity client) throws AuthenticationException {
|
|
||||||
|
|
||||||
Map<String, String> authorizationParameters = Maps.newHashMap();
|
|
||||||
OAuth2Request clientAuth = new OAuth2Request(authorizationParameters, client.getClientId(),
|
|
||||||
Sets.newHashSet(new SimpleGrantedAuthority("ROLE_CLIENT")), true,
|
|
||||||
Sets.newHashSet(OAuth2AccessTokenEntity.REGISTRATION_TOKEN_SCOPE), null, null, null);
|
|
||||||
OAuth2Authentication authentication = new OAuth2Authentication(clientAuth, null);
|
|
||||||
|
|
||||||
OAuth2AccessTokenEntity token = new OAuth2AccessTokenEntity();
|
|
||||||
token.setClient(client);
|
|
||||||
token.setScope(Sets.newHashSet(OAuth2AccessTokenEntity.REGISTRATION_TOKEN_SCOPE));
|
|
||||||
|
|
||||||
AuthenticationHolderEntity authHolder = new AuthenticationHolderEntity();
|
|
||||||
authHolder.setAuthentication(authentication);
|
|
||||||
authHolder = authenticationHolderRepository.save(authHolder);
|
|
||||||
token.setAuthenticationHolder(authHolder);
|
|
||||||
|
|
||||||
JWTClaimsSet claims = new JWTClaimsSet();
|
|
||||||
|
|
||||||
claims.setAudience(Lists.newArrayList(client.getClientId()));
|
|
||||||
claims.setIssuer(configBean.getIssuer());
|
|
||||||
claims.setIssueTime(new Date());
|
|
||||||
claims.setExpirationTime(token.getExpiration());
|
|
||||||
claims.setJWTID(UUID.randomUUID().toString()); // set a random NONCE in the middle of it
|
|
||||||
|
|
||||||
// TODO: use client's default signing algorithm
|
|
||||||
JWSAlgorithm signingAlg = jwtService.getDefaultSigningAlgorithm();
|
|
||||||
SignedJWT signed = new SignedJWT(new JWSHeader(signingAlg), claims);
|
|
||||||
|
|
||||||
jwtService.signJwt(signed);
|
|
||||||
|
|
||||||
token.setJwt(signed);
|
|
||||||
|
|
||||||
tokenService.saveAccessToken(token);
|
|
||||||
|
|
||||||
return token;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue