whitespace, import, brace, annotation, and format cleanups

pull/334/head
Justin Richer 2013-05-02 10:47:15 -04:00
parent b663cd5f8d
commit 8afab04544
135 changed files with 4236 additions and 4319 deletions

View File

@ -1,83 +1,85 @@
package org.mitre.oauth2.introspectingfilter;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.provider.AuthorizationRequest;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
public class AuthorizationRequestImpl implements AuthorizationRequest {
private JsonObject token;
private String clientId;
private Set<String> scopes = null;
public AuthorizationRequestImpl(JsonObject token) {
this.token = token;
clientId = token.get("client_id").getAsString();
scopes = new HashSet<String>();
for (JsonElement e : token.get("scope").getAsJsonArray()) {
scopes.add(e.getAsString());
}
}
private JsonObject token;
private String clientId;
private Set<String> scopes = null;
@Override
public Map<String, String> getAuthorizationParameters() {
return null;
}
public AuthorizationRequestImpl(JsonObject token) {
this.token = token;
clientId = token.get("client_id").getAsString();
scopes = new HashSet<String>();
for (JsonElement e : token.get("scope").getAsJsonArray()) {
scopes.add(e.getAsString());
}
}
@Override
public Map<String, String> getApprovalParameters() {
return null;
}
@Override
public Map<String, String> getAuthorizationParameters() {
return null;
}
@Override
public String getClientId() {
return clientId;
}
@Override
public Map<String, String> getApprovalParameters() {
return null;
}
@Override
public Set<String> getScope() {
@Override
public String getClientId() {
return clientId;
}
return scopes;
}
@Override
public Set<String> getScope() {
@Override
public Set<String> getResourceIds() {
return null;
}
return scopes;
}
@Override
public Collection<GrantedAuthority> getAuthorities() {
return null;
}
@Override
public Set<String> getResourceIds() {
return null;
}
@Override
public boolean isApproved() {
return true;
}
@Override
public Collection<GrantedAuthority> getAuthorities() {
return null;
}
@Override
public boolean isDenied() {
return false;
}
@Override
public boolean isApproved() {
return true;
}
@Override
public String getState() {
return null;
}
@Override
public boolean isDenied() {
return false;
}
@Override
public String getRedirectUri() {
return null;
}
@Override
public String getState() {
return null;
}
@Override
public Set<String> getResponseTypes() {
return null;
}
@Override
public String getRedirectUri() {
return null;
}
@Override
public Set<String> getResponseTypes() {
return null;
}
}

View File

@ -1,27 +1,14 @@
package org.mitre.oauth2.introspectingfilter;
import com.google.common.collect.Sets;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.provider.AuthorizationRequest;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
@ -31,171 +18,175 @@ import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
public class IntrospectingTokenService implements ResourceServerTokenServices {
private String clientId;
private String clientSecret;
private String introspectionUrl;
// Inner class to store in the hash map
private class TokenCacheObject { OAuth2AccessToken token; OAuth2Authentication auth;
private TokenCacheObject(OAuth2AccessToken token, OAuth2Authentication auth) {
this.token = token;
this.auth = auth;
}
}
private Map<String, TokenCacheObject> authCache = new HashMap<String, TokenCacheObject>();
public String getIntrospectionUrl() {
return introspectionUrl;
}
private String clientId;
private String clientSecret;
private String introspectionUrl;
public void setIntrospectionUrl(String introspectionUrl) {
this.introspectionUrl = introspectionUrl;
}
// Inner class to store in the hash map
private class TokenCacheObject { OAuth2AccessToken token; OAuth2Authentication auth;
private TokenCacheObject(OAuth2AccessToken token, OAuth2Authentication auth) {
this.token = token;
this.auth = auth;
}
}
private Map<String, TokenCacheObject> authCache = new HashMap<String, TokenCacheObject>();
public String getClientId() {
return clientId;
}
public String getIntrospectionUrl() {
return introspectionUrl;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public void setIntrospectionUrl(String introspectionUrl) {
this.introspectionUrl = introspectionUrl;
}
public String getClientSecret() {
return clientSecret;
}
public String getClientId() {
return clientId;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
// Check if there is a token and authentication in the cache
// and check if it is not expired.
private TokenCacheObject checkCache(String key) {
if(authCache.containsKey(key)) {
TokenCacheObject tco = authCache.get(key);
if (tco.token.getExpiration().after(new Date())) {
return tco;
} else {
// if the token is expired, don't keep things around.
authCache.remove(key);
}
}
return null;
}
private AuthorizationRequest createAuthRequest(final JsonObject token) {
AuthorizationRequest authReq = new AuthorizationRequestImpl(token);
return authReq;
}
// create a default authentication object with authority ROLE_API
private Authentication createAuthentication(JsonObject token){
// TODO: make role/authority configurable somehow
return new PreAuthenticatedAuthenticationToken(token.get("subject").getAsString(), null, AuthorityUtils.createAuthorityList("ROLE_API"));
}
private OAuth2AccessToken createAccessToken(final JsonObject token, final String tokenString){
OAuth2AccessToken accessToken = new OAuth2AccessTokenImpl(token, tokenString);
return accessToken;
}
// Validate a token string against the introspection endpoint,
// then parse it and store it in the local cache. Return true on
// sucess, false otherwise.
private boolean parseToken(String accessToken) {
String validatedToken = null;
// Use the SpringFramework RestTemplate to send the request to the endpoint
RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
form.add("token",accessToken);
form.add("client_id", this.clientId);
form.add("client_secret", this.clientSecret);
try {
validatedToken = restTemplate.postForObject(introspectionUrl, form, String.class);
} catch (RestClientException rce) {
// TODO: LOG THIS!?
LoggerFactory.getLogger(IntrospectingTokenService.class).error("validateToken", rce);
}
if (validatedToken != null) {
// parse the json
JsonElement jsonRoot = new JsonParser().parse(validatedToken);
if (!jsonRoot.isJsonObject()) {
return false; // didn't get a proper JSON object
}
JsonObject tokenResponse = jsonRoot.getAsJsonObject();
if (tokenResponse.get("error") != null) {
// report an error?
return false;
}
if (!tokenResponse.get("valid").getAsBoolean()){
// non-valid token
return false;
}
// create an OAuth2Authentication
OAuth2Authentication auth = new OAuth2Authentication(createAuthRequest(tokenResponse), createAuthentication(tokenResponse));
// create an OAuth2AccessToken
OAuth2AccessToken token = createAccessToken(tokenResponse, accessToken);
if (token.getExpiration().after(new Date())){
// Store them in the cache
authCache.put(accessToken, new TokenCacheObject(token,auth));
return true;
}
}
// If we never put a token and an authentication in the cache...
return false;
}
@Override
public OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException {
// First check if the in memory cache has an Authentication object, and that it is still valid
// If Valid, return it
TokenCacheObject cacheAuth = checkCache(accessToken);
if (cacheAuth != null) {
return cacheAuth.auth;
} else {
if (parseToken(accessToken)) {
cacheAuth = authCache.get(accessToken);
if (cacheAuth != null && (cacheAuth.token.getExpiration().after(new Date()))) {
return cacheAuth.auth;
} else {
return null;
}
} else {
return null;
}
}
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
@Override
public OAuth2AccessToken readAccessToken(String accessToken) {
// First check if the in memory cache has a Token object, and that it is still valid
// If Valid, return it
TokenCacheObject cacheAuth = checkCache(accessToken);
if (cacheAuth != null) {
return cacheAuth.token;
} else {
if (parseToken(accessToken)) {
cacheAuth = authCache.get(accessToken);
if (cacheAuth != null && (cacheAuth.token.getExpiration().after(new Date()))) {
return cacheAuth.token;
} else {
return null;
}
} else {
return null;
}
}
}
public String getClientSecret() {
return clientSecret;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
// Check if there is a token and authentication in the cache
// and check if it is not expired.
private TokenCacheObject checkCache(String key) {
if(authCache.containsKey(key)) {
TokenCacheObject tco = authCache.get(key);
if (tco.token.getExpiration().after(new Date())) {
return tco;
} else {
// if the token is expired, don't keep things around.
authCache.remove(key);
}
}
return null;
}
private AuthorizationRequest createAuthRequest(final JsonObject token) {
AuthorizationRequest authReq = new AuthorizationRequestImpl(token);
return authReq;
}
// create a default authentication object with authority ROLE_API
private Authentication createAuthentication(JsonObject token){
// TODO: make role/authority configurable somehow
return new PreAuthenticatedAuthenticationToken(token.get("subject").getAsString(), null, AuthorityUtils.createAuthorityList("ROLE_API"));
}
private OAuth2AccessToken createAccessToken(final JsonObject token, final String tokenString){
OAuth2AccessToken accessToken = new OAuth2AccessTokenImpl(token, tokenString);
return accessToken;
}
// Validate a token string against the introspection endpoint,
// then parse it and store it in the local cache. Return true on
// sucess, false otherwise.
private boolean parseToken(String accessToken) {
String validatedToken = null;
// Use the SpringFramework RestTemplate to send the request to the endpoint
RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
form.add("token",accessToken);
form.add("client_id", this.clientId);
form.add("client_secret", this.clientSecret);
try {
validatedToken = restTemplate.postForObject(introspectionUrl, form, String.class);
} catch (RestClientException rce) {
// TODO: LOG THIS!?
LoggerFactory.getLogger(IntrospectingTokenService.class).error("validateToken", rce);
}
if (validatedToken != null) {
// parse the json
JsonElement jsonRoot = new JsonParser().parse(validatedToken);
if (!jsonRoot.isJsonObject()) {
return false; // didn't get a proper JSON object
}
JsonObject tokenResponse = jsonRoot.getAsJsonObject();
if (tokenResponse.get("error") != null) {
// report an error?
return false;
}
if (!tokenResponse.get("valid").getAsBoolean()){
// non-valid token
return false;
}
// create an OAuth2Authentication
OAuth2Authentication auth = new OAuth2Authentication(createAuthRequest(tokenResponse), createAuthentication(tokenResponse));
// create an OAuth2AccessToken
OAuth2AccessToken token = createAccessToken(tokenResponse, accessToken);
if (token.getExpiration().after(new Date())){
// Store them in the cache
authCache.put(accessToken, new TokenCacheObject(token,auth));
return true;
}
}
// If we never put a token and an authentication in the cache...
return false;
}
@Override
public OAuth2Authentication loadAuthentication(String accessToken) throws AuthenticationException {
// First check if the in memory cache has an Authentication object, and that it is still valid
// If Valid, return it
TokenCacheObject cacheAuth = checkCache(accessToken);
if (cacheAuth != null) {
return cacheAuth.auth;
} else {
if (parseToken(accessToken)) {
cacheAuth = authCache.get(accessToken);
if (cacheAuth != null && (cacheAuth.token.getExpiration().after(new Date()))) {
return cacheAuth.auth;
} else {
return null;
}
} else {
return null;
}
}
}
@Override
public OAuth2AccessToken readAccessToken(String accessToken) {
// First check if the in memory cache has a Token object, and that it is still valid
// If Valid, return it
TokenCacheObject cacheAuth = checkCache(accessToken);
if (cacheAuth != null) {
return cacheAuth.token;
} else {
if (parseToken(accessToken)) {
cacheAuth = authCache.get(accessToken);
if (cacheAuth != null && (cacheAuth.token.getExpiration().after(new Date()))) {
return cacheAuth.token;
} else {
return null;
}
} else {
return null;
}
}
}
}

View File

@ -1,7 +1,5 @@
package org.mitre.oauth2.introspectingfilter;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@ -12,79 +10,83 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
public class OAuth2AccessTokenImpl implements OAuth2AccessToken {
private JsonObject token;
private String tokenString;
private Set<String> scopes = null;
private Date expireDate;
public OAuth2AccessTokenImpl(JsonObject token, String tokenString) {
this.token = token;
this.tokenString = tokenString;
scopes = new HashSet<String>();
for (JsonElement e : token.get("scope").getAsJsonArray()) {
scopes.add(e.getAsString());
}
DateFormat dateFormater = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
try {
expireDate = dateFormater.parse(token.get("expires_at").getAsString());
} catch (ParseException ex) {
Logger.getLogger(IntrospectingTokenService.class.getName()).log(Level.SEVERE, null, ex);
}
}
private JsonObject token;
private String tokenString;
private Set<String> scopes = null;
private Date expireDate;
@Override
public Map<String, Object> getAdditionalInformation() {
return null;
}
public OAuth2AccessTokenImpl(JsonObject token, String tokenString) {
this.token = token;
this.tokenString = tokenString;
scopes = new HashSet<String>();
for (JsonElement e : token.get("scope").getAsJsonArray()) {
scopes.add(e.getAsString());
}
@Override
public Set<String> getScope() {
return scopes;
}
DateFormat dateFormater = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
try {
expireDate = dateFormater.parse(token.get("expires_at").getAsString());
} catch (ParseException ex) {
Logger.getLogger(IntrospectingTokenService.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public OAuth2RefreshToken getRefreshToken() {
return null;
}
@Override
public String getTokenType() {
return BEARER_TYPE;
}
@Override
public Map<String, Object> getAdditionalInformation() {
return null;
}
@Override
public boolean isExpired() {
if (expireDate != null && expireDate.before(new Date())) {
return true;
}
return false;
}
@Override
public Set<String> getScope() {
return scopes;
}
@Override
public Date getExpiration() {
return expireDate;
}
@Override
public OAuth2RefreshToken getRefreshToken() {
return null;
}
@Override
public int getExpiresIn() {
if (expireDate != null) {
return (int)TimeUnit.MILLISECONDS.toSeconds(expireDate.getTime() - (new Date()).getTime());
}
return 0;
}
@Override
public String getTokenType() {
return BEARER_TYPE;
}
@Override
public String getValue() {
return tokenString;
}
@Override
public boolean isExpired() {
if (expireDate != null && expireDate.before(new Date())) {
return true;
}
return false;
}
@Override
public Date getExpiration() {
return expireDate;
}
@Override
public int getExpiresIn() {
if (expireDate != null) {
return (int)TimeUnit.MILLISECONDS.toSeconds(expireDate.getTime() - (new Date()).getTime());
}
return 0;
}
@Override
public String getValue() {
return tokenString;
}
}

View File

@ -3,10 +3,8 @@
*/
package org.mitre.openid.connect.client;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.security.core.GrantedAuthority;
@ -24,26 +22,26 @@ import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper
*
*/
public class NamedAdminAuthoritiesMapper implements GrantedAuthoritiesMapper {
private static final SimpleGrantedAuthority ROLE_ADMIN = new SimpleGrantedAuthority("ROLE_ADMIN");
private static final SimpleGrantedAuthority ROLE_USER = new SimpleGrantedAuthority("ROLE_USER");
private static final SimpleGrantedAuthority ROLE_ADMIN = new SimpleGrantedAuthority("ROLE_ADMIN");
private static final SimpleGrantedAuthority ROLE_USER = new SimpleGrantedAuthority("ROLE_USER");
private Set<SubjectIssuerGrantedAuthority> admins = new HashSet<SubjectIssuerGrantedAuthority>();
private GrantedAuthoritiesMapper chain = new NullAuthoritiesMapper();
@Override
public Collection<? extends GrantedAuthority> mapAuthorities(Collection<? extends GrantedAuthority> authorities) {
Set<GrantedAuthority> out = new HashSet<GrantedAuthority>();
out.addAll(authorities);
for (GrantedAuthority authority : authorities) {
if (admins.contains(authority)) {
out.add(ROLE_ADMIN);
}
}
}
// everybody's a user by default
out.add(ROLE_USER);

View File

@ -20,8 +20,6 @@ import java.math.BigInteger;
import java.security.SecureRandom;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@ -29,8 +27,6 @@ import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringUtils;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.DefaultHttpClient;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.jwt.signer.service.impl.JWKSetSigningAndValidationServiceCacheService;
@ -74,7 +70,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
protected final static int HTTP_SOCKET_TIMEOUT = 30000;
protected final static String FILTER_PROCESSES_URL = "/openid_connect_login";
// Allow for time sync issues by having a window of X seconds.
private int timeSkewAllowance = 300;
@ -86,7 +82,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
private ClientConfigurationService clients;
private IssuerService issuerService;
private AuthRequestUrlBuilder authRequestBuilder;
protected int httpSocketTimeout = HTTP_SOCKET_TIMEOUT;
/**
@ -119,18 +115,18 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
// there's an error coming back from the server, need to handle this
handleError(request, response);
return null; // no auth, response is sent to display page or something
} else if (!Strings.isNullOrEmpty(request.getParameter("code"))) {
// we got back the code, need to process this to get our tokens
Authentication auth = handleAuthorizationCodeResponse(request, response);
return auth;
} else {
// not an error, not a code, must be an initial login of some type
handleAuthorizationRequest(request, response);
return null; // no auth, response redirected to the server's Auth Endpoint (or possibly to the account chooser)
}
@ -149,53 +145,53 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
protected void handleAuthorizationRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
HttpSession session = request.getSession();
IssuerServiceResponse issResp = issuerService.getIssuer(request);
if (issResp == null) {
logger.error("Null issuer response returned from service.");
throw new AuthenticationServiceException("No issuer found.");
}
if (issResp.shouldRedirect()) {
response.sendRedirect(issResp.getRedirectUrl());
} else {
String issuer = issResp.getIssuer();
if (Strings.isNullOrEmpty(issuer)) {
logger.error("No issuer found: " + issuer);
throw new AuthenticationServiceException("No issuer found: " + issuer);
}
session.setAttribute(ISSUER_SESSION_VARIABLE, issuer);
ServerConfiguration serverConfig = servers.getServerConfiguration(issuer);
if (serverConfig == null) {
logger.error("No server configuration found for issuer: " + issuer);
throw new AuthenticationServiceException("No server configuration found for issuer: " + issuer);
}
ClientDetails clientConfig = clients.getClientConfiguration(serverConfig);
if (clientConfig == null) {
logger.error("No client configuration found for issuer: " + issuer);
throw new AuthenticationServiceException("No client configuration found for issuer: " + issuer);
}
// our redirect URI is this current URL, with no query parameters
String redirectUri = request.getRequestURL().toString();
session.setAttribute(REDIRECT_URI_SESION_VARIABLE, redirectUri);
// this value comes back in the id token and is checked there
String nonce = createNonce(session);
// this value comes back in the auth code response
String state = createState(session);
String authRequest = authRequestBuilder.buildAuthRequestUrl(serverConfig, clientConfig, redirectUri, nonce, state);
logger.debug("Auth Request: " + authRequest);
response.sendRedirect(authRequest);
}
}
@ -210,9 +206,9 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
protected Authentication handleAuthorizationCodeResponse(HttpServletRequest request, HttpServletResponse response) {
String authorizationCode = request.getParameter("code");
HttpSession session = request.getSession();
// check for state, if it doesn't match we bail early
String storedState = getStoredState(session);
if (!StringUtils.isBlank(storedState)) {
@ -224,20 +220,20 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
// look up the issuer that we set out to talk to
String issuer = getStoredSessionString(session, ISSUER_SESSION_VARIABLE);
// pull the configurations based on that issuer
ServerConfiguration serverConfig = servers.getServerConfiguration(issuer);
ClientDetails clientConfig = clients.getClientConfiguration(serverConfig);
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
form.add("grant_type", "authorization_code");
form.add("code", authorizationCode);
String redirectUri = getStoredSessionString(session, REDIRECT_URI_SESION_VARIABLE);
if (redirectUri != null) {
form.add("redirect_uri", redirectUri);
}
// Handle Token Endpoint interaction
DefaultHttpClient httpClient = new DefaultHttpClient();
@ -252,7 +248,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
*/
form.add("client_id", clientConfig.getClientId());
form.add("client_secret", clientConfig.getClientSecret());
/**/
/**/
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
@ -277,14 +273,14 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
}
logger.debug("from TokenEndpoint jsonString = " + jsonString);
JsonElement jsonRoot = new JsonParser().parse(jsonString);
if (!jsonRoot.isJsonObject()) {
throw new AuthenticationServiceException("Token Endpoint did not return a JSON object: " + jsonRoot);
}
JsonObject tokenResponse = jsonRoot.getAsJsonObject();
if (tokenResponse.get("error") != null) {
// Handle error
@ -299,125 +295,125 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
// Extract the id_token to insert into the
// OIDCAuthenticationToken
// get out all the token strings
String accessTokenValue = null;
String idTokenValue = null;
String refreshTokenValue = null;
if (tokenResponse.has("access_token")) {
accessTokenValue = tokenResponse.get("access_token").getAsString();
} else {
throw new AuthenticationServiceException("Token Endpoint did not return an access_token: " + jsonString);
}
if (tokenResponse.has("id_token")) {
idTokenValue = tokenResponse.get("id_token").getAsString();
} else {
logger.error("Token Endpoint did not return an id_token");
throw new AuthenticationServiceException("Token Endpoint did not return an id_token");
}
if (tokenResponse.has("refresh_token")) {
refreshTokenValue = tokenResponse.get("refresh_token").getAsString();
}
try {
SignedJWT idToken = SignedJWT.parse(idTokenValue);
SignedJWT idToken = SignedJWT.parse(idTokenValue);
// validate our ID Token over a number of tests
ReadOnlyJWTClaimsSet idClaims = idToken.getJWTClaimsSet();
// check the signature
JwtSigningAndValidationService jwtValidator = validationServices.get(serverConfig.getJwksUri());
if (jwtValidator != null) {
if(!jwtValidator.validateSignature(idToken)) {
throw new AuthenticationServiceException("Signature validation failed");
}
} else {
logger.info("No validation service found. Skipping signature validation");
}
// check the issuer
if (idClaims.getIssuer() == null) {
throw new AuthenticationServiceException("Id Token Issuer is null");
} else if (!idClaims.getIssuer().equals(serverConfig.getIssuer())){
throw new AuthenticationServiceException("Issuers do not match, expected " + serverConfig.getIssuer() + " got " + idClaims.getIssuer());
}
// check expiration
if (idClaims.getExpirationTime() == null) {
throw new AuthenticationServiceException("Id Token does not have required expiration claim");
} else {
// it's not null, see if it's expired
Date now = new Date(System.currentTimeMillis() - (timeSkewAllowance * 1000));
if (now.after(idClaims.getExpirationTime())) {
throw new AuthenticationServiceException("Id Token is expired: " + idClaims.getExpirationTime());
}
}
// check not before
if (idClaims.getNotBeforeTime() != null) {
Date now = new Date(System.currentTimeMillis() + (timeSkewAllowance * 1000));
if (now.before(idClaims.getNotBeforeTime())){
throw new AuthenticationServiceException("Id Token not valid untill: " + idClaims.getNotBeforeTime());
}
}
// check issued at
if (idClaims.getIssueTime() == null) {
throw new AuthenticationServiceException("Id Token does not have required issued-at claim");
} else {
// since it's not null, see if it was issued in the future
Date now = new Date(System.currentTimeMillis() + (timeSkewAllowance * 1000));
if (now.before(idClaims.getIssueTime())) {
throw new AuthenticationServiceException("Id Token was issued in the future: " + idClaims.getIssueTime());
}
}
// check audience
if (idClaims.getAudience() == null) {
throw new AuthenticationServiceException("Id token audience is null");
} else if (!idClaims.getAudience().contains(clientConfig.getClientId())) {
throw new AuthenticationServiceException("Audience does not match, expected " + clientConfig.getClientId() + " got " + idClaims.getAudience());
}
// compare the nonce to our stored claim
// FIXME: Nimbus claims as strings?
String nonce = (String) idClaims.getCustomClaim("nonce");
if (StringUtils.isBlank(nonce)) {
logger.error("ID token did not contain a nonce claim.");
// validate our ID Token over a number of tests
ReadOnlyJWTClaimsSet idClaims = idToken.getJWTClaimsSet();
throw new AuthenticationServiceException("ID token did not contain a nonce claim.");
}
// check the signature
JwtSigningAndValidationService jwtValidator = validationServices.get(serverConfig.getJwksUri());
if (jwtValidator != null) {
if(!jwtValidator.validateSignature(idToken)) {
throw new AuthenticationServiceException("Signature validation failed");
}
} else {
logger.info("No validation service found. Skipping signature validation");
}
String storedNonce = getStoredNonce(session);
if (!nonce.equals(storedNonce)) {
logger.error("Possible replay attack detected! The comparison of the nonce in the returned "
+ "ID Token to the session " + NONCE_SESSION_VARIABLE + " failed. Expected " + storedNonce + " got " + nonce + ".");
// check the issuer
if (idClaims.getIssuer() == null) {
throw new AuthenticationServiceException("Id Token Issuer is null");
} else if (!idClaims.getIssuer().equals(serverConfig.getIssuer())){
throw new AuthenticationServiceException("Issuers do not match, expected " + serverConfig.getIssuer() + " got " + idClaims.getIssuer());
}
throw new AuthenticationServiceException(
"Possible replay attack detected! The comparison of the nonce in the returned "
+ "ID Token to the session " + NONCE_SESSION_VARIABLE + " failed. Expected " + storedNonce + " got " + nonce + ".");
}
// check expiration
if (idClaims.getExpirationTime() == null) {
throw new AuthenticationServiceException("Id Token does not have required expiration claim");
} else {
// it's not null, see if it's expired
Date now = new Date(System.currentTimeMillis() - (timeSkewAllowance * 1000));
if (now.after(idClaims.getExpirationTime())) {
throw new AuthenticationServiceException("Id Token is expired: " + idClaims.getExpirationTime());
}
}
// pull the subject (user id) out as a claim on the id_token
String userId = idClaims.getSubject();
// construct an OIDCAuthenticationToken and return a Authentication object w/the userId and the idToken
OIDCAuthenticationToken token = new OIDCAuthenticationToken(userId, idClaims.getIssuer(), serverConfig, idTokenValue, accessTokenValue, refreshTokenValue);
// check not before
if (idClaims.getNotBeforeTime() != null) {
Date now = new Date(System.currentTimeMillis() + (timeSkewAllowance * 1000));
if (now.before(idClaims.getNotBeforeTime())){
throw new AuthenticationServiceException("Id Token not valid untill: " + idClaims.getNotBeforeTime());
}
}
Authentication authentication = this.getAuthenticationManager().authenticate(token);
// check issued at
if (idClaims.getIssueTime() == null) {
throw new AuthenticationServiceException("Id Token does not have required issued-at claim");
} else {
// since it's not null, see if it was issued in the future
Date now = new Date(System.currentTimeMillis() + (timeSkewAllowance * 1000));
if (now.before(idClaims.getIssueTime())) {
throw new AuthenticationServiceException("Id Token was issued in the future: " + idClaims.getIssueTime());
}
}
// check audience
if (idClaims.getAudience() == null) {
throw new AuthenticationServiceException("Id token audience is null");
} else if (!idClaims.getAudience().contains(clientConfig.getClientId())) {
throw new AuthenticationServiceException("Audience does not match, expected " + clientConfig.getClientId() + " got " + idClaims.getAudience());
}
// compare the nonce to our stored claim
// FIXME: Nimbus claims as strings?
String nonce = (String) idClaims.getCustomClaim("nonce");
if (StringUtils.isBlank(nonce)) {
logger.error("ID token did not contain a nonce claim.");
throw new AuthenticationServiceException("ID token did not contain a nonce claim.");
}
String storedNonce = getStoredNonce(session);
if (!nonce.equals(storedNonce)) {
logger.error("Possible replay attack detected! The comparison of the nonce in the returned "
+ "ID Token to the session " + NONCE_SESSION_VARIABLE + " failed. Expected " + storedNonce + " got " + nonce + ".");
throw new AuthenticationServiceException(
"Possible replay attack detected! The comparison of the nonce in the returned "
+ "ID Token to the session " + NONCE_SESSION_VARIABLE + " failed. Expected " + storedNonce + " got " + nonce + ".");
}
// pull the subject (user id) out as a claim on the id_token
String userId = idClaims.getSubject();
// construct an OIDCAuthenticationToken and return a Authentication object w/the userId and the idToken
OIDCAuthenticationToken token = new OIDCAuthenticationToken(userId, idClaims.getIssuer(), serverConfig, idTokenValue, accessTokenValue, refreshTokenValue);
Authentication authentication = this.getAuthenticationManager().authenticate(token);
return authentication;
} catch (ParseException e) {
throw new AuthenticationServiceException("Couldn't parse idToken: ", e);
}
return authentication;
} catch (ParseException e) {
throw new AuthenticationServiceException("Couldn't parse idToken: ", e);
}
}
}
@ -456,7 +452,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
return null;
}
}
/**
* Create a cryptographically random nonce and store it in the session
* @param session
@ -477,7 +473,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
protected static String getStoredNonce(HttpSession session) {
return getStoredSessionString(session, NONCE_SESSION_VARIABLE);
}
/**
* Create a cryptographically random state and store it in the session
* @param session
@ -486,10 +482,10 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
protected static String createState(HttpSession session) {
String state = new BigInteger(50, new SecureRandom()).toString(16);
session.setAttribute(STATE_SESSION_VARIABLE, state);
return state;
}
/**
* Get the state we stored in the session
* @param session
@ -498,14 +494,14 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
protected static String getStoredState(HttpSession session) {
return getStoredSessionString(session, STATE_SESSION_VARIABLE);
}
//
// Getters and setters for configuration variables
//
public int getTimeSkewAllowance() {
return timeSkewAllowance;
}
@ -582,6 +578,6 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
*/
public void setAuthRequestUrlBuilder(AuthRequestUrlBuilder authRequestBuilder) {
this.authRequestBuilder = authRequestBuilder;
}
}
}

View File

@ -22,25 +22,21 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
/**
* @author nemonik
*
*/
public class OIDCAuthenticationProvider implements
AuthenticationProvider, InitializingBean {
AuthenticationProvider, InitializingBean {
private UserInfoFetcher userInfoFetcher = new UserInfoFetcher();
private GrantedAuthoritiesMapper authoritiesMapper = new NamedAdminAuthoritiesMapper();
/*
@ -69,24 +65,24 @@ public class OIDCAuthenticationProvider implements
if (authentication instanceof OIDCAuthenticationToken) {
OIDCAuthenticationToken token = (OIDCAuthenticationToken) authentication;
Collection<SubjectIssuerGrantedAuthority> authorities = Lists.newArrayList(new SubjectIssuerGrantedAuthority(token.getSub(), token.getIssuer()));
UserInfo userInfo = userInfoFetcher.loadUserInfo(token);
if (userInfo == null) {
// TODO: user Info not found -- error?
} else {
} else {
if (!Strings.isNullOrEmpty(userInfo.getSub()) && !userInfo.getSub().equals(token.getSub())) {
// the userinfo came back and the user_id fields don't match what was in the id_token
throw new UsernameNotFoundException("user_id mismatch between id_token and user_info call: " + userInfo.getSub() + " / " + token.getSub());
}
}
return new OIDCAuthenticationToken(token.getSub(),
token.getIssuer(),
return new OIDCAuthenticationToken(token.getSub(),
token.getIssuer(),
userInfo, authoritiesMapper.mapAuthorities(authorities),
token.getIdTokenValue(), token.getAccessTokenValue(), token.getRefreshTokenValue());
}

View File

@ -32,8 +32,8 @@ import com.google.common.collect.ImmutableMap;
*/
public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
private static final long serialVersionUID = 22100073066377804L;
private static final long serialVersionUID = 22100073066377804L;
private final Object principal;
private final String idTokenValue; // string representation of the id token
private final String accessTokenValue; // string representation of the access token
@ -43,7 +43,7 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
private final transient ServerConfiguration serverConfiguration; // server configuration used to fulfill this token, don't serialize it
private final transient UserInfo userInfo; // user info container, don't serialize it b/c it might be huge and can be re-fetched
/**
* Constructs OIDCAuthenticationToken with a full set of authorities, marking this as authenticated.
*
@ -55,7 +55,7 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
* @param principal
* @param idToken
*/
public OIDCAuthenticationToken(String subject, String issuer,
public OIDCAuthenticationToken(String subject, String issuer,
UserInfo userInfo, Collection<? extends GrantedAuthority> authorities,
String idTokenValue, String accessTokenValue, String refreshTokenValue) {
@ -70,12 +70,12 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
this.refreshTokenValue = refreshTokenValue;
this.serverConfiguration = null; // we don't need a server config anymore
setAuthenticated(true);
}
/**
* Constructs OIDCAuthenticationToken for use as a data shuttle from the filter to the auth provider.
* Constructs OIDCAuthenticationToken for use as a data shuttle from the filter to the auth provider.
*
* Set to not-authenticated.
*
@ -83,8 +83,8 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
* @param sub
* @param idToken
*/
public OIDCAuthenticationToken(String subject, String issuer,
ServerConfiguration serverConfiguration,
public OIDCAuthenticationToken(String subject, String issuer,
ServerConfiguration serverConfiguration,
String idTokenValue, String accessTokenValue, String refreshTokenValue) {
super(new ArrayList<GrantedAuthority>(0));
@ -97,10 +97,10 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
this.refreshTokenValue = refreshTokenValue;
this.userInfo = null; // we don't have a UserInfo yet
this.serverConfiguration = serverConfiguration;
setAuthenticated(false);
}
@ -128,46 +128,46 @@ public class OIDCAuthenticationToken extends AbstractAuthenticationToken {
}
/**
* @return the idTokenValue
*/
public String getIdTokenValue() {
return idTokenValue;
}
* @return the idTokenValue
*/
public String getIdTokenValue() {
return idTokenValue;
}
/**
* @return the accessTokenValue
*/
public String getAccessTokenValue() {
return accessTokenValue;
}
* @return the accessTokenValue
*/
public String getAccessTokenValue() {
return accessTokenValue;
}
/**
* @return the refreshTokenValue
*/
public String getRefreshTokenValue() {
return refreshTokenValue;
}
* @return the refreshTokenValue
*/
public String getRefreshTokenValue() {
return refreshTokenValue;
}
/**
* @return the serverConfiguration
*/
public ServerConfiguration getServerConfiguration() {
return serverConfiguration;
}
* @return the serverConfiguration
*/
public ServerConfiguration getServerConfiguration() {
return serverConfiguration;
}
/**
* @return the issuer
*/
public String getIssuer() {
return issuer;
}
* @return the issuer
*/
public String getIssuer() {
return issuer;
}
/**
* @return the userInfo
*/
public UserInfo getUserInfo() {
return userInfo;
}
* @return the userInfo
*/
public UserInfo getUserInfo() {
return userInfo;
}
}

View File

@ -16,22 +16,22 @@ import com.google.common.base.Strings;
*/
public class SubjectIssuerGrantedAuthority implements GrantedAuthority {
private static final long serialVersionUID = 5584978219226664794L;
private static final long serialVersionUID = 5584978219226664794L;
private final String subject;
private final String issuer;
/**
* @param subject
* @param issuer
*/
public SubjectIssuerGrantedAuthority(String subject, String issuer) {
if (Strings.isNullOrEmpty(subject) || Strings.isNullOrEmpty(issuer)) {
throw new IllegalArgumentException("Neither subject nor issuer may be null or empty");
}
this.subject = subject;
this.issuer = issuer;
}
public SubjectIssuerGrantedAuthority(String subject, String issuer) {
if (Strings.isNullOrEmpty(subject) || Strings.isNullOrEmpty(issuer)) {
throw new IllegalArgumentException("Neither subject nor issuer may be null or empty");
}
this.subject = subject;
this.issuer = issuer;
}
/**
* Returns a string formed by concatenating the subject with the issuer, separated by _ and prepended with OIDC_
@ -44,67 +44,67 @@ public class SubjectIssuerGrantedAuthority implements GrantedAuthority {
public String getAuthority() {
return "OIDC_" + subject + "_" + issuer;
}
/**
* @return the subject
*/
public String getSubject() {
return subject;
}
public String getSubject() {
return subject;
}
/**
/**
* @return the issuer
*/
public String getIssuer() {
return issuer;
}
public String getIssuer() {
return issuer;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((issuer == null) ? 0 : issuer.hashCode());
result = prime * result + ((subject == null) ? 0 : subject.hashCode());
return result;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((issuer == null) ? 0 : issuer.hashCode());
result = prime * result + ((subject == null) ? 0 : subject.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof SubjectIssuerGrantedAuthority)) {
return false;
}
SubjectIssuerGrantedAuthority other = (SubjectIssuerGrantedAuthority) obj;
if (issuer == null) {
if (other.issuer != null) {
return false;
}
} else if (!issuer.equals(other.issuer)) {
return false;
}
if (subject == null) {
if (other.subject != null) {
return false;
}
} else if (!subject.equals(other.subject)) {
return false;
}
return true;
}
@Override
public String toString() {
return getAuthority();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof SubjectIssuerGrantedAuthority)) {
return false;
}
SubjectIssuerGrantedAuthority other = (SubjectIssuerGrantedAuthority) obj;
if (issuer == null) {
if (other.issuer != null) {
return false;
}
} else if (!issuer.equals(other.issuer)) {
return false;
}
if (subject == null) {
if (other.subject != null) {
return false;
}
} else if (!subject.equals(other.subject)) {
return false;
}
return true;
}
@Override
public String toString() {
return getAuthority();
}
}

View File

@ -15,7 +15,7 @@ import com.google.gson.JsonParser;
public class UserInfoFetcher {
public UserInfo loadUserInfo(OIDCAuthenticationToken token) {
HttpClient httpClient = new DefaultHttpClient();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
@ -25,15 +25,15 @@ public class UserInfoFetcher {
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
form.add("access_token", token.getAccessTokenValue());
form.add("schema", "openid");
String userInfoString = restTemplate.postForObject(token.getServerConfiguration().getUserInfoUri(), form, String.class);
JsonObject userInfoJson = new JsonParser().parse(userInfoString).getAsJsonObject();
UserInfo userInfo = DefaultUserInfo.fromJson(userInfoJson);
return userInfo;
}
}
}

View File

@ -34,16 +34,16 @@ public class ClientKeyPublisher implements BeanDefinitionRegistryPostProcessor {
/**
* If either the jwkPublishUrl or x509PublishUrl fields are set on this bean, set up a listener on that URL to publish keys.
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if (!Strings.isNullOrEmpty(getJwkPublishUrl())) {
// add a mapping to this class
BeanDefinitionBuilder clientKeyMapping = BeanDefinitionBuilder.rootBeanDefinition(ClientKeyPublisherMapping.class);
// custom view resolver
BeanDefinitionBuilder viewResolver = BeanDefinitionBuilder.rootBeanDefinition(JwkViewResolver.class);
if (!Strings.isNullOrEmpty(getJwkPublishUrl())) {
clientKeyMapping.addPropertyValue("jwkPublishUrl", getJwkPublishUrl());
@ -56,49 +56,49 @@ public class ClientKeyPublisher implements BeanDefinitionRegistryPostProcessor {
registry.registerBeanDefinition("jwkKeyList", jwkView.getBeanDefinition());
viewResolver.addPropertyReference("jwk", "jwkKeyList");
}
registry.registerBeanDefinition("clientKeyMapping", clientKeyMapping.getBeanDefinition());
registry.registerBeanDefinition("jwkViewResolver", viewResolver.getBeanDefinition());
}
}
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(org.springframework.beans.factory.support.BeanDefinitionRegistry)
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
* @see org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(org.springframework.beans.factory.support.BeanDefinitionRegistry)
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
this.registry = registry;
}
}
/**
* Return a view to publish all keys in JWK format. Only used if jwkPublishUrl is set.
* @return
*/
* Return a view to publish all keys in JWK format. Only used if jwkPublishUrl is set.
* @return
*/
public ModelAndView publishClientJwk() {
// map from key id to key
Map<String, JWK> keys = signingAndValidationService.getAllPublicKeys();
// TODO: check if keys are empty, return a 404 here or just an empty list?
return new ModelAndView(jwkViewName, "keys", keys);
}
/**
* @return the jwkPublishUrl
*/
public String getJwkPublishUrl() {
return jwkPublishUrl;
}
* @return the jwkPublishUrl
*/
public String getJwkPublishUrl() {
return jwkPublishUrl;
}
/**
* @param jwkPublishUrl the jwkPublishUrl to set
*/
public void setJwkPublishUrl(String jwkPublishUrl) {
this.jwkPublishUrl = jwkPublishUrl;
}
* @param jwkPublishUrl the jwkPublishUrl to set
*/
public void setJwkPublishUrl(String jwkPublishUrl) {
this.jwkPublishUrl = jwkPublishUrl;
}
/**
* @return the signingAndValidationService

View File

@ -19,72 +19,72 @@ public class ClientKeyPublisherMapping extends RequestMappingInfoHandlerMapping
private String jwkPublishUrl;
private String x509PublishUrl;
/* (non-Javadoc)
* @see org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#isHandler(java.lang.Class)
*/
@Override
protected boolean isHandler(Class<?> beanType) {
return beanType.equals(ClientKeyPublisher.class);
}
* @see org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#isHandler(java.lang.Class)
*/
@Override
protected boolean isHandler(Class<?> beanType) {
return beanType.equals(ClientKeyPublisher.class);
}
/**
* Map the "jwkKeyPublish" method to our jwkPublishUrl.
* Map the "x509KeyPublish" method to our x509PublishUrl.
*/
@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
if (method.getName().equals("publishClientJwk") && getJwkPublishUrl() != null) {
return new RequestMappingInfo(
new PatternsRequestCondition(new String[] {getJwkPublishUrl()}, getUrlPathHelper(), getPathMatcher(), false, false),
null,
null,
null,
null,
null,
null);
} else if (method.getName().equals("publishClientx509") && getX509PublishUrl() != null) {
return new RequestMappingInfo(
new PatternsRequestCondition(new String[] {getX509PublishUrl()}, getUrlPathHelper(), getPathMatcher(), false, false),
null,
null,
null,
null,
null,
null);
} else {
return null;
}
}
*/
@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
if (method.getName().equals("publishClientJwk") && getJwkPublishUrl() != null) {
return new RequestMappingInfo(
new PatternsRequestCondition(new String[] {getJwkPublishUrl()}, getUrlPathHelper(), getPathMatcher(), false, false),
null,
null,
null,
null,
null,
null);
} else if (method.getName().equals("publishClientx509") && getX509PublishUrl() != null) {
return new RequestMappingInfo(
new PatternsRequestCondition(new String[] {getX509PublishUrl()}, getUrlPathHelper(), getPathMatcher(), false, false),
null,
null,
null,
null,
null,
null);
} else {
return null;
}
}
/**
* @return the jwkPublishUrl
*/
public String getJwkPublishUrl() {
return jwkPublishUrl;
}
* @return the jwkPublishUrl
*/
public String getJwkPublishUrl() {
return jwkPublishUrl;
}
/**
* @param jwkPublishUrl the jwkPublishUrl to set
*/
public void setJwkPublishUrl(String jwkPublishUrl) {
this.jwkPublishUrl = jwkPublishUrl;
}
* @param jwkPublishUrl the jwkPublishUrl to set
*/
public void setJwkPublishUrl(String jwkPublishUrl) {
this.jwkPublishUrl = jwkPublishUrl;
}
/**
* @return the x509PublishUrl
*/
public String getX509PublishUrl() {
return x509PublishUrl;
}
* @return the x509PublishUrl
*/
public String getX509PublishUrl() {
return x509PublishUrl;
}
/**
* @param x509PublishUrl the x509PublishUrl to set
*/
public void setX509PublishUrl(String x509PublishUrl) {
this.x509PublishUrl = x509PublishUrl;
}
* @param x509PublishUrl the x509PublishUrl to set
*/
public void setX509PublishUrl(String x509PublishUrl) {
this.x509PublishUrl = x509PublishUrl;
}
}

View File

@ -20,12 +20,12 @@ public class JwkViewResolver implements ViewResolver, Ordered {
private String jwkViewName = "jwkKeyList";
private View jwk;
private String x509ViewName = "x509certs";
private View x509;
private int order = HIGHEST_PRECEDENCE; // highest precedence, most specific -- avoids hitting the catch-all view resolvers
/**
* Map "jwkKeyList" to the jwk property and "x509certs" to the x509 property on this bean.
* Everything else returns null
@ -46,74 +46,74 @@ public class JwkViewResolver implements ViewResolver, Ordered {
}
/**
* @return the x509
*/
public View getX509() {
return x509;
}
* @return the x509
*/
public View getX509() {
return x509;
}
/**
* @param x509 the x509 to set
*/
public void setX509(View x509) {
this.x509 = x509;
}
* @param x509 the x509 to set
*/
public void setX509(View x509) {
this.x509 = x509;
}
/**
* @return the jwk
*/
public View getJwk() {
return jwk;
}
* @return the jwk
*/
public View getJwk() {
return jwk;
}
/**
* @param jwk the jwk to set
*/
public void setJwk(View jwk) {
this.jwk = jwk;
}
* @param jwk the jwk to set
*/
public void setJwk(View jwk) {
this.jwk = jwk;
}
/**
* @return the order
*/
@Override
public int getOrder() {
return order;
}
* @return the order
*/
@Override
public int getOrder() {
return order;
}
/**
* @param order the order to set
*/
public void setOrder(int order) {
this.order = order;
}
* @param order the order to set
*/
public void setOrder(int order) {
this.order = order;
}
/**
* @return the jwkViewName
*/
public String getJwkViewName() {
return jwkViewName;
}
* @return the jwkViewName
*/
public String getJwkViewName() {
return jwkViewName;
}
/**
* @param jwkViewName the jwkViewName to set
*/
public void setJwkViewName(String jwkViewName) {
this.jwkViewName = jwkViewName;
}
* @param jwkViewName the jwkViewName to set
*/
public void setJwkViewName(String jwkViewName) {
this.jwkViewName = jwkViewName;
}
/**
* @return the x509ViewName
*/
public String getX509ViewName() {
return x509ViewName;
}
* @return the x509ViewName
*/
public String getX509ViewName() {
return x509ViewName;
}
/**
* @param x509ViewName the x509ViewName to set
*/
public void setX509ViewName(String x509ViewName) {
this.x509ViewName = x509ViewName;
}
* @param x509ViewName the x509ViewName to set
*/
public void setX509ViewName(String x509ViewName) {
this.x509ViewName = x509ViewName;
}
}

View File

@ -16,24 +16,24 @@ public class IssuerServiceResponse {
private String loginHint;
private String targetLinkUri;
private String redirectUrl;
/**
* @param issuer
* @param loginHint
* @param targetLinkUri
*/
public IssuerServiceResponse(String issuer, String loginHint, String targetLinkUri) {
this.issuer = issuer;
this.loginHint = loginHint;
this.targetLinkUri = targetLinkUri;
}
public IssuerServiceResponse(String issuer, String loginHint, String targetLinkUri) {
this.issuer = issuer;
this.loginHint = loginHint;
this.targetLinkUri = targetLinkUri;
}
/**
* @param redirectUrl
*/
public IssuerServiceResponse(String redirectUrl) {
this.redirectUrl = redirectUrl;
}
public IssuerServiceResponse(String redirectUrl) {
this.redirectUrl = redirectUrl;
}
/**
* @return the issuer
*/
@ -82,12 +82,12 @@ public class IssuerServiceResponse {
public void setRedirectUrl(String redirectUrl) {
this.redirectUrl = redirectUrl;
}
/**
* If the redirect url has been set, then we should send a redirect using it instead of processing things.
*/
public boolean shouldRedirect() {
return this.redirectUrl != null;
}
}

View File

@ -20,6 +20,6 @@ public interface AuthRequestUrlBuilder {
* @param state
* @return
*/
public String buildAuthRequestUrl(ServerConfiguration serverConfig, ClientDetails clientConfig, String redirectUri, String nonce, String state);
public String buildAuthRequestUrl(ServerConfiguration serverConfig, ClientDetails clientConfig, String redirectUri, String nonce, String state);
}

View File

@ -13,5 +13,5 @@ import org.springframework.security.oauth2.provider.ClientDetails;
public interface ClientConfigurationService {
public ClientDetails getClientConfiguration(ServerConfiguration issuer);
}

View File

@ -17,5 +17,5 @@ import org.mitre.openid.connect.client.model.IssuerServiceResponse;
public interface IssuerService {
public IssuerServiceResponse getIssuer(HttpServletRequest request);
}

View File

@ -12,5 +12,5 @@ import org.mitre.openid.connect.config.ServerConfiguration;
public interface ServerConfigurationService {
public ServerConfiguration getServerConfiguration(String issuer);
}

View File

@ -24,7 +24,6 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
@ -35,66 +34,66 @@ import com.google.gson.JsonParser;
public class DynamicRegistrationClientConfigurationService implements ClientConfigurationService {
private static Logger logger = LoggerFactory.getLogger(DynamicServerConfigurationService.class);
private LoadingCache<ServerConfiguration, ClientDetailsEntity> clients;
private ClientDetailsEntity template;
public DynamicRegistrationClientConfigurationService() {
clients = CacheBuilder.newBuilder().build(new DynamicClientRegistrationLoader());
}
@Override
public ClientDetails getClientConfiguration(ServerConfiguration issuer) {
try {
return clients.get(issuer);
} catch (ExecutionException e) {
logger.warn("Unable to get client configuration", e);
return null;
}
return clients.get(issuer);
} catch (ExecutionException e) {
logger.warn("Unable to get client configuration", e);
return null;
}
}
/**
/**
* @return the template
*/
public ClientDetailsEntity getTemplate() {
return template;
}
public ClientDetailsEntity getTemplate() {
return template;
}
/**
* @param template the template to set
*/
public void setTemplate(ClientDetailsEntity template) {
this.template = template;
}
public void setTemplate(ClientDetailsEntity template) {
this.template = template;
}
public class DynamicClientRegistrationLoader extends CacheLoader<ServerConfiguration, ClientDetailsEntity> {
private HttpClient httpClient = new DefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private JsonParser parser = new JsonParser();
@Override
public ClientDetailsEntity load(ServerConfiguration serverConfig) throws Exception {
RestTemplate restTemplate = new RestTemplate(httpFactory);
// dynamically register this client
JsonObject jsonRequest = ClientDetailsEntityJsonProcessor.serialize(template, null, null);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Lists.newArrayList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>(jsonRequest.toString(), headers);
String registered = restTemplate.postForObject(serverConfig.getRegistrationEndpointUri(), entity, String.class);
// TODO: handle HTTP errors
// TODO: save registration token and other important bits
ClientDetailsEntity client = ClientDetailsEntityJsonProcessor.parse(registered);
return client;
}
@Override
public ClientDetailsEntity load(ServerConfiguration serverConfig) throws Exception {
RestTemplate restTemplate = new RestTemplate(httpFactory);
}
// dynamically register this client
JsonObject jsonRequest = ClientDetailsEntityJsonProcessor.serialize(template, null, null);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Lists.newArrayList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>(jsonRequest.toString(), headers);
String registered = restTemplate.postForObject(serverConfig.getRegistrationEndpointUri(), entity, String.class);
// TODO: handle HTTP errors
// TODO: save registration token and other important bits
ClientDetailsEntity client = ClientDetailsEntityJsonProcessor.parse(registered);
return client;
}
}
}

View File

@ -31,72 +31,72 @@ import com.google.gson.JsonParser;
public class DynamicServerConfigurationService implements ServerConfigurationService {
private static Logger logger = LoggerFactory.getLogger(DynamicServerConfigurationService.class);
// map of issuer -> server configuration, loaded dynamically from service discovery
private LoadingCache<String, ServerConfiguration> servers;
public DynamicServerConfigurationService() {
// initialize the cache
servers = CacheBuilder.newBuilder().build(new OpenIDConnectServiceConfigurationFetcher());
}
@Override
public ServerConfiguration getServerConfiguration(String issuer) {
try {
return servers.get(issuer);
} catch (ExecutionException e) {
logger.warn("Couldn't load configuration for " + issuer, e);
return null;
}
return servers.get(issuer);
} catch (ExecutionException e) {
logger.warn("Couldn't load configuration for " + issuer, e);
return null;
}
}
/**
* @author jricher
*
*/
private class OpenIDConnectServiceConfigurationFetcher extends CacheLoader<String, ServerConfiguration> {
private HttpClient httpClient = new DefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
* @author jricher
*
*/
private class OpenIDConnectServiceConfigurationFetcher extends CacheLoader<String, ServerConfiguration> {
private HttpClient httpClient = new DefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private JsonParser parser = new JsonParser();
@Override
public ServerConfiguration load(String issuer) throws Exception {
RestTemplate restTemplate = new RestTemplate(httpFactory);
@Override
public ServerConfiguration load(String issuer) throws Exception {
RestTemplate restTemplate = new RestTemplate(httpFactory);
// data holder
ServerConfiguration conf = new ServerConfiguration();
// construct the well-known URI
String url = issuer + "/.well-known/openid-configuration";
// fetch the value
String jsonString = restTemplate.getForObject(url, String.class);
// data holder
ServerConfiguration conf = new ServerConfiguration();
JsonElement parsed = parser.parse(jsonString);
if (parsed.isJsonObject()) {
JsonObject o = parsed.getAsJsonObject();
// sanity checks
if (!issuer.equals(o.get("issuer").getAsString())) {
throw new IllegalStateException("Discovered issuers didn't match, expected " + issuer + " got " + o.get("issuer").getAsString());
}
conf.setIssuer(o.get("issuer").getAsString());
conf.setAuthorizationEndpointUri(o.get("authorization_endpoint").getAsString());
conf.setTokenEndpointUri(o.get("token_endpoint").getAsString());
conf.setJwksUri(o.get("jwks_uri").getAsString());
conf.setUserInfoUri(o.get("userinfo_endpoint").getAsString());
conf.setRegistrationEndpointUri(o.get("registration_endpoint").getAsString());
// construct the well-known URI
String url = issuer + "/.well-known/openid-configuration";
return conf;
} else {
throw new IllegalStateException("Couldn't parse server discovery results for " + url);
}
}
// fetch the value
String jsonString = restTemplate.getForObject(url, String.class);
}
JsonElement parsed = parser.parse(jsonString);
if (parsed.isJsonObject()) {
JsonObject o = parsed.getAsJsonObject();
// sanity checks
if (!issuer.equals(o.get("issuer").getAsString())) {
throw new IllegalStateException("Discovered issuers didn't match, expected " + issuer + " got " + o.get("issuer").getAsString());
}
conf.setIssuer(o.get("issuer").getAsString());
conf.setAuthorizationEndpointUri(o.get("authorization_endpoint").getAsString());
conf.setTokenEndpointUri(o.get("token_endpoint").getAsString());
conf.setJwksUri(o.get("jwks_uri").getAsString());
conf.setUserInfoUri(o.get("userinfo_endpoint").getAsString());
conf.setRegistrationEndpointUri(o.get("registration_endpoint").getAsString());
return conf;
} else {
throw new IllegalStateException("Couldn't parse server discovery results for " + url);
}
}
}
}

View File

@ -28,7 +28,7 @@ public class PlainAuthRequestUrlBuilder implements AuthRequestUrlBuilder {
@Override
public String buildAuthRequestUrl(ServerConfiguration serverConfig, ClientDetails clientConfig, String redirectUri, String nonce, String state) {
try {
URIBuilder uriBuilder = new URIBuilder(serverConfig.getAuthorizationEndpointUri());
uriBuilder.addParameter("response_type", "code");
uriBuilder.addParameter("client_id", clientConfig.getClientId());
@ -39,20 +39,20 @@ public class PlainAuthRequestUrlBuilder implements AuthRequestUrlBuilder {
uriBuilder.addParameter("nonce", nonce);
uriBuilder.addParameter("state", state);
// Optional parameters:
// TODO: display, prompt
return uriBuilder.build().toString();
} catch (URISyntaxException e) {
throw new AuthenticationServiceException("Malformed Authorization Endpoint Uri", e);
}
return uriBuilder.build().toString();
} catch (URISyntaxException e) {
throw new AuthenticationServiceException("Malformed Authorization Endpoint Uri", e);
}
}
}

View File

@ -4,11 +4,6 @@
package org.mitre.openid.connect.client.service.impl;
import java.net.URISyntaxException;
import java.security.NoSuchAlgorithmException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.http.client.utils.URIBuilder;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
@ -38,34 +33,34 @@ public class SignedAuthRequestUrlBuilder implements AuthRequestUrlBuilder {
// create our signed JWT for the request object
JWTClaimsSet claims = new JWTClaimsSet();
//set parameters to JwtClaims
claims.setCustomClaim("response_type", "code");
claims.setCustomClaim("client_id", clientConfig.getClientId());
claims.setCustomClaim("scope", Joiner.on(" ").join(clientConfig.getScope()));
// build our redirect URI
claims.setCustomClaim("redirect_uri", redirectUri);
// this comes back in the id token
claims.setCustomClaim("nonce", nonce);
// this comes back in the auth request return
claims.setCustomClaim("state", state);
SignedJWT jwt = new SignedJWT(new JWSHeader(signingAndValidationService.getDefaultSigningAlgorithm()), claims);
signingAndValidationService.signJwt(jwt);
try {
URIBuilder uriBuilder = new URIBuilder(serverConfig.getAuthorizationEndpointUri());
uriBuilder.addParameter("request", jwt.serialize());
// build out the URI
return uriBuilder.build().toString();
} catch (URISyntaxException e) {
throw new AuthenticationServiceException("Malformed Authorization Endpoint Uri", e);
}
URIBuilder uriBuilder = new URIBuilder(serverConfig.getAuthorizationEndpointUri());
uriBuilder.addParameter("request", jwt.serialize());
// build out the URI
return uriBuilder.build().toString();
} catch (URISyntaxException e) {
throw new AuthenticationServiceException("Malformed Authorization Endpoint Uri", e);
}
}
/**

View File

@ -22,7 +22,7 @@ public class StaticClientConfigurationService implements ClientConfigurationServ
// Map of issuer URL -> client configuration information
private Map<String, ClientDetails> clients;
/**
* @return the clients
*/
@ -44,19 +44,19 @@ public class StaticClientConfigurationService implements ClientConfigurationServ
*/
@Override
public ClientDetails getClientConfiguration(ServerConfiguration issuer) {
return clients.get(issuer.getIssuer());
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws Exception {
if (clients == null || clients.isEmpty()) {
throw new IllegalArgumentException("Clients map cannot be null or empty");
}
}
@Override
public void afterPropertiesSet() throws Exception {
if (clients == null || clients.isEmpty()) {
throw new IllegalArgumentException("Clients map cannot be null or empty");
}
}
}

View File

@ -45,12 +45,12 @@ public class StaticServerConfigurationService implements ServerConfigurationServ
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws Exception {
if (servers == null || servers.isEmpty()) {
throw new IllegalArgumentException("Servers map cannot be null or empty.");
}
}
@Override
public void afterPropertiesSet() throws Exception {
if (servers == null || servers.isEmpty()) {
throw new IllegalArgumentException("Servers map cannot be null or empty.");
}
}
}

View File

@ -16,7 +16,7 @@ import com.google.common.base.Strings;
*
*/
public class StaticSingleIssuerService implements IssuerService, InitializingBean {
private String issuer;
/**
@ -46,13 +46,13 @@ public class StaticSingleIssuerService implements IssuerService, InitializingBea
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws Exception {
@Override
public void afterPropertiesSet() throws Exception {
if (Strings.isNullOrEmpty(issuer)) {
throw new IllegalArgumentException("Issuer must not be null or empty.");
}
}
if (Strings.isNullOrEmpty(issuer)) {
throw new IllegalArgumentException("Issuer must not be null or empty.");
}
}
}

View File

@ -25,34 +25,34 @@ import com.google.common.base.Strings;
public class ThirdPartyIssuerService implements IssuerService, InitializingBean {
private String accountChooserUrl;
/* (non-Javadoc)
* @see org.mitre.openid.connect.client.service.IssuerService#getIssuer(javax.servlet.http.HttpServletRequest)
*/
@Override
public IssuerServiceResponse getIssuer(HttpServletRequest request) {
// if the issuer is passed in, return that
if (!Strings.isNullOrEmpty(request.getParameter("iss"))) {
return new IssuerServiceResponse(request.getParameter("iss"), request.getParameter("login_hint"), request.getParameter("target_link_uri"));
} else {
try {
// otherwise, need to forward to the account chooser
String redirectUri = request.getRequestURL().toString();
URIBuilder builder = new URIBuilder(accountChooserUrl);
builder.addParameter("redirect_uri", redirectUri);
return new IssuerServiceResponse(builder.build().toString());
} catch (URISyntaxException e) {
throw new AuthenticationServiceException("Account Chooser URL is not valid", e);
}
URIBuilder builder = new URIBuilder(accountChooserUrl);
builder.addParameter("redirect_uri", redirectUri);
return new IssuerServiceResponse(builder.build().toString());
} catch (URISyntaxException e) {
throw new AuthenticationServiceException("Account Chooser URL is not valid", e);
}
}
}
/**
@ -72,12 +72,12 @@ public class ThirdPartyIssuerService implements IssuerService, InitializingBean
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws Exception {
if (Strings.isNullOrEmpty(this.accountChooserUrl)) {
throw new IllegalArgumentException("Account Chooser URL cannot be null or empty");
}
}
@Override
public void afterPropertiesSet() throws Exception {
if (Strings.isNullOrEmpty(this.accountChooserUrl)) {
throw new IllegalArgumentException("Account Chooser URL cannot be null or empty");
}
}
}

View File

@ -36,7 +36,7 @@ import com.google.gson.JsonParser;
public class WebfingerIssuerService implements IssuerService {
private static Logger logger = LoggerFactory.getLogger(WebfingerIssuerService.class);
// pattern used to parse user input; we can't use the built-in java URI parser
private static final Pattern pattern = Pattern.compile("(https://|acct:|http://|mailto:)?(([^@]+)@)?([^\\?]+)(\\?([^#]+))?(#(.*))?");
@ -47,7 +47,7 @@ public class WebfingerIssuerService implements IssuerService {
* Name of the incoming parameter to check for discovery purposes.
*/
private String parameterName = "identifier";
/**
* URL of the page to forward to if no identifier is given.
*/
@ -56,53 +56,53 @@ public class WebfingerIssuerService implements IssuerService {
public WebfingerIssuerService() {
issuers = CacheBuilder.newBuilder().build(new WebfingerIssuerFetcher());
}
/* (non-Javadoc)
* @see org.mitre.openid.connect.client.service.IssuerService#getIssuer(javax.servlet.http.HttpServletRequest)
*/
@Override
public IssuerServiceResponse getIssuer(HttpServletRequest request) {
String identifier = request.getParameter(parameterName);
if (!Strings.isNullOrEmpty(identifier)) {
try {
String issuer = issuers.get(normalizeResource(identifier));
return new IssuerServiceResponse(issuer, null, null);
} catch (ExecutionException e) {
logger.warn("Issue fetching issuer for user input: " + identifier, e);
return null;
}
try {
String issuer = issuers.get(normalizeResource(identifier));
return new IssuerServiceResponse(issuer, null, null);
} catch (ExecutionException e) {
logger.warn("Issue fetching issuer for user input: " + identifier, e);
return null;
}
} else {
logger.warn("No user input given, directing to login page: " + loginPageUrl);
return new IssuerServiceResponse(loginPageUrl);
}
}
/**
* Normalize the resource string as per OIDC Discovery.
* @param identifier
* @return the normalized string, or null if the string can't be normalized
*/
private NormalizedURI normalizeResource(String identifier) {
// try to parse the URI
// try to parse the URI
// NOTE: we can't use the Java built-in URI class because it doesn't split the parts appropriately
if (Strings.isNullOrEmpty(identifier)) {
logger.warn("Can't normalize null or empty URI: " + identifier);
return null; // nothing we can do
} else {
NormalizedURI n = new NormalizedURI();
Matcher m = pattern.matcher(identifier);
NormalizedURI n = new NormalizedURI();
Matcher m = pattern.matcher(identifier);
if (m.matches()) {
n.scheme = m.group(1); // includes colon and maybe initial slashes
n.user = m.group(2); // includes at sign
n.hostportpath = m.group(4);
n.query = m.group(5); // includes question mark
n.hash = m.group(7); // includes hash mark
// normalize scheme portion
if (Strings.isNullOrEmpty(n.scheme)) {
if (!Strings.isNullOrEmpty(n.user)) {
@ -113,24 +113,24 @@ public class WebfingerIssuerService implements IssuerService {
n.scheme = "https://";
}
}
n.source = Strings.nullToEmpty(n.scheme) +
Strings.nullToEmpty(n.user) +
Strings.nullToEmpty(n.hostportpath) +
Strings.nullToEmpty(n.hostportpath) +
Strings.nullToEmpty(n.query); // note: leave fragment off
return n;
} else {
logger.warn("Parser couldn't match input: " + identifier);
return null;
}
}
}
/**
* @return the parameterName
*/
@ -162,82 +162,82 @@ public class WebfingerIssuerService implements IssuerService {
/**
* @author jricher
*
*/
private class WebfingerIssuerFetcher extends CacheLoader<NormalizedURI, String> {
private HttpClient httpClient = new DefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
* @author jricher
*
*/
private class WebfingerIssuerFetcher extends CacheLoader<NormalizedURI, String> {
private HttpClient httpClient = new DefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private JsonParser parser = new JsonParser();
@Override
public String load(NormalizedURI key) throws Exception {
public String load(NormalizedURI key) throws Exception {
RestTemplate restTemplate = new RestTemplate(httpFactory);
// construct the URL to go to
//String url = "https://" + key.hostportpath + "/.well-known/webfinger?resource="
String scheme = key.scheme;
if (!Strings.isNullOrEmpty(scheme) && !scheme.startsWith("http")) {
// do discovery on http or https URLs
scheme = "https://";
}
URIBuilder builder = new URIBuilder(scheme + key.hostportpath + "/.well-known/webfinger" + Strings.nullToEmpty(key.query));
builder.addParameter("resource", key.source);
builder.addParameter("rel", "http://openid.net/specs/connect/1.0/issuer");
// do the fetch
logger.info("Loading: " + builder.toString());
String webfingerResponse = restTemplate.getForObject(builder.build(), String.class);
RestTemplate restTemplate = new RestTemplate(httpFactory);
// construct the URL to go to
// TODO: catch and handle HTTP errors
JsonElement json = parser.parse(webfingerResponse);
// TODO: catch and handle JSON errors
if (json != null && json.isJsonObject()) {
// find the issuer
JsonArray links = json.getAsJsonObject().get("links").getAsJsonArray();
for (JsonElement link : links) {
if (link.isJsonObject()) {
JsonObject linkObj = link.getAsJsonObject();
if (linkObj.has("href")
&& linkObj.has("rel")
&& linkObj.get("rel").getAsString().equals("http://openid.net/specs/connect/1.0/issuer")) {
// we found the issuer, return it
return linkObj.get("href").getAsString();
}
}
}
}
// we couldn't find it
logger.warn("Couldn't find issuer");
return null;
}
//String url = "https://" + key.hostportpath + "/.well-known/webfinger?resource="
String scheme = key.scheme;
if (!Strings.isNullOrEmpty(scheme) && !scheme.startsWith("http")) {
// do discovery on http or https URLs
scheme = "https://";
}
URIBuilder builder = new URIBuilder(scheme + key.hostportpath + "/.well-known/webfinger" + Strings.nullToEmpty(key.query));
builder.addParameter("resource", key.source);
builder.addParameter("rel", "http://openid.net/specs/connect/1.0/issuer");
}
// do the fetch
logger.info("Loading: " + builder.toString());
String webfingerResponse = restTemplate.getForObject(builder.build(), String.class);
// TODO: catch and handle HTTP errors
JsonElement json = parser.parse(webfingerResponse);
// TODO: catch and handle JSON errors
if (json != null && json.isJsonObject()) {
// find the issuer
JsonArray links = json.getAsJsonObject().get("links").getAsJsonArray();
for (JsonElement link : links) {
if (link.isJsonObject()) {
JsonObject linkObj = link.getAsJsonObject();
if (linkObj.has("href")
&& linkObj.has("rel")
&& linkObj.get("rel").getAsString().equals("http://openid.net/specs/connect/1.0/issuer")) {
// we found the issuer, return it
return linkObj.get("href").getAsString();
}
}
}
}
// we couldn't find it
logger.warn("Couldn't find issuer");
return null;
}
}
/**
* Simple data shuttle class to represent the parsed components of a URI.
*
* @author jricher
*
*/
private class NormalizedURI {
public String scheme;
public String user;
public String hostportpath;
public String query;
public String hash;
public String source;
}
/**
* Simple data shuttle class to represent the parsed components of a URI.
*
* @author jricher
*
*/
private class NormalizedURI {
public String scheme;
public String user;
public String hostportpath;
public String query;
public String hash;
public String source;
}
}

View File

@ -1,10 +1,5 @@
package org.mitre.openid.connect.client;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* Unit test for OIDCAuthenticationFilter
@ -18,10 +13,10 @@ public class AbstractOIDCAuthenticationFilterTest {
//@Autowired
private OIDCAuthenticationFilter filter;
//@Test
public void testUrlConstruction() {
}
/**
@ -37,7 +32,7 @@ public class AbstractOIDCAuthenticationFilterTest {
public void setFilter(OIDCAuthenticationFilter filter) {
this.filter = filter;
}
}

View File

@ -5,7 +5,6 @@ package org.mitre.jose;
import javax.persistence.Basic;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.Transient;
import com.google.common.base.Strings;
@ -22,16 +21,16 @@ import com.nimbusds.jose.JWEAlgorithm;
public class JWEAlgorithmEmbed {
public static final JWEAlgorithmEmbed NONE = getForAlgorithmName("none");
private JWEAlgorithm algorithm;
public JWEAlgorithmEmbed() {
}
public JWEAlgorithmEmbed(JWEAlgorithm algorithm) {
this.algorithm = algorithm;
}
this.algorithm = algorithm;
}
public static JWEAlgorithmEmbed getForAlgorithmName (String algorithmName) {
JWEAlgorithmEmbed ent = new JWEAlgorithmEmbed();
@ -42,7 +41,7 @@ public class JWEAlgorithmEmbed {
return ent;
}
}
/**
* Get the name of this algorithm, return null if no algorithm set.
* @return
@ -55,9 +54,9 @@ public class JWEAlgorithmEmbed {
return null;
}
}
/**
* Set the name of this algorithm.
* Set the name of this algorithm.
* Calls JWEAlgorithm.parse()
* @param algorithmName
*/
@ -72,15 +71,15 @@ public class JWEAlgorithmEmbed {
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "JWEAlgorithmEmbed [algorithm=" + algorithm + "]";
}
@Override
public String toString() {
return "JWEAlgorithmEmbed [algorithm=" + algorithm + "]";
}
/**
* @return the algorithm
*/
@Transient
@Transient
public JWEAlgorithm getAlgorithm() {
return algorithm;
}
@ -91,5 +90,5 @@ public class JWEAlgorithmEmbed {
public void setAlgorithm(JWEAlgorithm algorithm) {
this.algorithm = algorithm;
}
}

View File

@ -9,7 +9,6 @@ import javax.persistence.Transient;
import com.google.common.base.Strings;
import com.nimbusds.jose.EncryptionMethod;
import com.nimbusds.jose.JWEAlgorithm;
/**
* @author jricher
@ -19,16 +18,16 @@ import com.nimbusds.jose.JWEAlgorithm;
public class JWEEncryptionMethodEmbed {
public static final JWEEncryptionMethodEmbed NONE = getForAlgorithmName("none");
private EncryptionMethod algorithm;
public JWEEncryptionMethodEmbed() {
}
public JWEEncryptionMethodEmbed(EncryptionMethod algorithm) {
this.algorithm = algorithm;
}
this.algorithm = algorithm;
}
public static JWEEncryptionMethodEmbed getForAlgorithmName (String algorithmName) {
JWEEncryptionMethodEmbed ent = new JWEEncryptionMethodEmbed();
@ -39,7 +38,7 @@ public class JWEEncryptionMethodEmbed {
return ent;
}
}
/**
* Get the name of this algorithm, return null if no algorithm set.
* @return
@ -52,9 +51,9 @@ public class JWEEncryptionMethodEmbed {
return null;
}
}
/**
* Set the name of this algorithm.
* Set the name of this algorithm.
* Calls EncryptionMethod.parse()
* @param algorithmName
*/
@ -69,15 +68,15 @@ public class JWEEncryptionMethodEmbed {
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "JWEEncryptionMethodEmbed [algorithm=" + algorithm + "]";
}
@Override
public String toString() {
return "JWEEncryptionMethodEmbed [algorithm=" + algorithm + "]";
}
/**
* @return the algorithm
*/
@Transient
@Transient
public EncryptionMethod getAlgorithm() {
return algorithm;
}
@ -88,6 +87,6 @@ public class JWEEncryptionMethodEmbed {
public void setAlgorithm(EncryptionMethod algorithm) {
this.algorithm = algorithm;
}
}

View File

@ -5,8 +5,6 @@ package org.mitre.jose;
import javax.persistence.Basic;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Transient;
import com.google.common.base.Strings;
@ -23,17 +21,17 @@ import com.nimbusds.jose.JWSAlgorithm;
public class JWSAlgorithmEmbed {
public static final JWSAlgorithmEmbed NONE = getForAlgorithmName("none");
private JWSAlgorithm algorithm;
public JWSAlgorithmEmbed() {
public JWSAlgorithmEmbed() {
}
public JWSAlgorithmEmbed(JWSAlgorithm algorithm) {
this.algorithm = algorithm;
}
this.algorithm = algorithm;
}
public static JWSAlgorithmEmbed getForAlgorithmName (String algorithmName) {
JWSAlgorithmEmbed ent = new JWSAlgorithmEmbed();
ent.setAlgorithmName(algorithmName);
@ -56,9 +54,9 @@ public class JWSAlgorithmEmbed {
return null;
}
}
/**
* Set the name of this algorithm.
* Set the name of this algorithm.
* Calls JWSAlgorithm.parse()
* @param algorithmName
*/
@ -88,11 +86,11 @@ public class JWSAlgorithmEmbed {
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "JWSAlgorithmEmbed [algorithm=" + algorithm + "]";
}
@Override
public String toString() {
return "JWSAlgorithmEmbed [algorithm=" + algorithm + "]";
}
}

View File

@ -21,26 +21,26 @@ import com.nimbusds.jose.jwk.JWKSet;
public class JWKSetKeyStore implements InitializingBean {
private JWKSet jwkSet;
private Resource location;
public JWKSetKeyStore() {
}
public JWKSetKeyStore(JWKSet jwkSet) {
this.jwkSet = jwkSet;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws Exception {
if (jwkSet == null) {
if (location != null) {
if (location.exists() && location.isReadable()) {
// read in the file from disk
@ -48,11 +48,11 @@ public class JWKSetKeyStore implements InitializingBean {
// parse it into a jwkSet object
jwkSet = JWKSet.parse(s);
} else {
throw new IllegalArgumentException("Key Set resource could not be read: " + location);
}
} else {
throw new IllegalArgumentException("Key store must be initialized with at least one of a jwkSet or a location.");
}
@ -90,10 +90,10 @@ public class JWKSetKeyStore implements InitializingBean {
/**
* Get the list of keys in this keystore. This is a passthrough to the underlying JWK Set
*/
public List<JWK> getKeys() {
return jwkSet.getKeys();
}
public List<JWK> getKeys() {
return jwkSet.getKeys();
}
}

View File

@ -16,7 +16,6 @@
package org.mitre.jwt.signer.service;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.util.Collection;
import java.util.Map;
@ -30,7 +29,7 @@ public interface JwtSigningAndValidationService {
* Get all public keys for this service, mapped by their Key ID
*/
public Map<String, JWK> getAllPublicKeys();
/**
* Checks the signature of the given JWT against all configured signers,
* returns true if at least one of the signers validates it.
@ -38,17 +37,17 @@ public interface JwtSigningAndValidationService {
* @param jwtString
* the string representation of the JWT as sent on the wire
* @return true if the signature is valid, false if not
* @throws NoSuchAlgorithmException
* @throws NoSuchAlgorithmException
*/
public boolean validateSignature(SignedJWT jwtString);
/**
* Called to sign a jwt in place for a client that hasn't registered a preferred signing algorithm.
* Use the default algorithm to sign.
*
* @param jwt the jwt to sign
* @return the signed jwt
* @throws NoSuchAlgorithmException
* @throws NoSuchAlgorithmException
*/
public void signJwt(SignedJWT jwt);
@ -56,13 +55,13 @@ public interface JwtSigningAndValidationService {
* Get the default signing algorithm for use when nothing else has been specified.
* @return
*/
public JWSAlgorithm getDefaultSigningAlgorithm();
public JWSAlgorithm getDefaultSigningAlgorithm();
/**
* Get the list of all signing algorithms supported by this service.
* Get the list of all signing algorithms supported by this service.
* @return
*/
public Collection<JWSAlgorithm> getAllSigningAlgsSupported();
public Collection<JWSAlgorithm> getAllSigningAlgsSupported();
/**
* Sign a jwt using the selected algorithm. The algorithm is selected using the String parameter values specified
@ -74,7 +73,7 @@ public interface JwtSigningAndValidationService {
*/
//TODO: implement later; only need signJwt(Jwt jwt) for now
//public Jwt signJwt(Jwt jwt, String alg);
/**
* TODO: method to sign a jwt using a specified algorithm and a key id
*/

View File

@ -55,9 +55,9 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
private static Logger logger = LoggerFactory.getLogger(DefaultJwtSigningAndValidationService.class);
private String defaultSignerKeyId;
private JWSAlgorithm defaultAlgorithm;
// map of identifier to key
private Map<String, JWK> keys = new HashMap<String, JWK>();
@ -73,10 +73,10 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
* @throws NoSuchAlgorithmException
* If there is no appropriate algorithm to tie the keys to.
*/
public DefaultJwtSigningAndValidationService(Map<String, JWK> keys) throws NoSuchAlgorithmException, InvalidKeySpecException {
this.keys = keys;
buildSignersAndVerifiers();
}
public DefaultJwtSigningAndValidationService(Map<String, JWK> keys) throws NoSuchAlgorithmException, InvalidKeySpecException {
this.keys = keys;
buildSignersAndVerifiers();
}
/**
* Build this service based on the given keystore. All keys must have a key
@ -90,18 +90,18 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
* @throws NoSuchAlgorithmException
* If there is no appropriate algorithm to tie the keys to.
*/
public DefaultJwtSigningAndValidationService(JWKSetKeyStore keyStore) throws NoSuchAlgorithmException, InvalidKeySpecException {
// convert all keys in the keystore to a map based on key id
for (JWK key : keyStore.getKeys()) {
if (!Strings.isNullOrEmpty(key.getKeyID())) {
this.keys.put(key.getKeyID(), key);
} else {
throw new IllegalArgumentException("Tried to load a key from a keystore without a 'kid' field: " + key);
}
}
buildSignersAndVerifiers();
}
public DefaultJwtSigningAndValidationService(JWKSetKeyStore keyStore) throws NoSuchAlgorithmException, InvalidKeySpecException {
// convert all keys in the keystore to a map based on key id
for (JWK key : keyStore.getKeys()) {
if (!Strings.isNullOrEmpty(key.getKeyID())) {
this.keys.put(key.getKeyID(), key);
} else {
throw new IllegalArgumentException("Tried to load a key from a keystore without a 'kid' field: " + key);
}
}
buildSignersAndVerifiers();
}
/**
* @return the defaultSignerKeyId
*/
@ -120,22 +120,22 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
* @return
*/
@Override
public JWSAlgorithm getDefaultSigningAlgorithm() {
return defaultAlgorithm;
}
public void setDefaultSigningAlgorithmName(String algName) {
defaultAlgorithm = JWSAlgorithm.parse(algName);
}
public String getDefaultSigningAlgorithmName() {
if (defaultAlgorithm != null) {
return defaultAlgorithm.getName();
} else {
return null;
}
}
public JWSAlgorithm getDefaultSigningAlgorithm() {
return defaultAlgorithm;
}
public void setDefaultSigningAlgorithmName(String algName) {
defaultAlgorithm = JWSAlgorithm.parse(algName);
}
public String getDefaultSigningAlgorithmName() {
if (defaultAlgorithm != null) {
return defaultAlgorithm.getName();
} else {
return null;
}
}
/*
* (non-Javadoc)
*
@ -148,9 +148,9 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
if (keys == null) {
throw new IllegalArgumentException("Signing and validation service must have at least one key configured.");
}
buildSignersAndVerifiers();
logger.info("DefaultJwtSigningAndValidationService is ready: " + this.toString());
}
@ -159,45 +159,45 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
* @throws InvalidKeySpecException If the keys in the JWKs are not valid
* @throws NoSuchAlgorithmException If there is no appropriate algorithm to tie the keys to.
*/
private void buildSignersAndVerifiers() throws NoSuchAlgorithmException, InvalidKeySpecException {
private void buildSignersAndVerifiers() throws NoSuchAlgorithmException, InvalidKeySpecException {
for (Map.Entry<String, JWK> jwkEntry : keys.entrySet()) {
String id = jwkEntry.getKey();
JWK jwk = jwkEntry.getValue();
if (jwk instanceof RSAKey) {
// build RSA signers & verifiers
if (jwk.isPrivate()) { // only add the signer if there's a private key
RSASSASigner signer = new RSASSASigner(((RSAKey) jwk).toRSAPrivateKey());
signers.put(id, signer);
}
RSASSAVerifier verifier = new RSASSAVerifier(((RSAKey) jwk).toRSAPublicKey());
verifiers.put(id, verifier);
} else if (jwk instanceof ECKey) {
// build EC signers & verifiers
// TODO: add support for EC keys
logger.warn("EC Keys are not yet supported.");
} else if (jwk instanceof OctetSequenceKey) {
// build HMAC signers & verifiers
if (jwk.isPrivate()) { // technically redundant check because all HMAC keys are private
MACSigner signer = new MACSigner(((OctetSequenceKey) jwk).toByteArray());
signers.put(id, signer);
}
MACVerifier verifier = new MACVerifier(((OctetSequenceKey) jwk).toByteArray());
verifiers.put(id, verifier);
} else {
logger.warn("Unknown key type: " + jwk);
}
}
}
if (jwk instanceof RSAKey) {
// build RSA signers & verifiers
if (jwk.isPrivate()) { // only add the signer if there's a private key
RSASSASigner signer = new RSASSASigner(((RSAKey) jwk).toRSAPrivateKey());
signers.put(id, signer);
}
RSASSAVerifier verifier = new RSASSAVerifier(((RSAKey) jwk).toRSAPublicKey());
verifiers.put(id, verifier);
} else if (jwk instanceof ECKey) {
// build EC signers & verifiers
// TODO: add support for EC keys
logger.warn("EC Keys are not yet supported.");
} else if (jwk instanceof OctetSequenceKey) {
// build HMAC signers & verifiers
if (jwk.isPrivate()) { // technically redundant check because all HMAC keys are private
MACSigner signer = new MACSigner(((OctetSequenceKey) jwk).toByteArray());
signers.put(id, signer);
}
MACVerifier verifier = new MACVerifier(((OctetSequenceKey) jwk).toByteArray());
verifiers.put(id, verifier);
} else {
logger.warn("Unknown key type: " + jwk);
}
}
}
/**
* Sign a jwt in place using the configured default signer.
@ -207,18 +207,18 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
if (getDefaultSignerKeyId() == null) {
throw new IllegalStateException("Tried to call default signing with no default signer ID set");
}
JWSSigner signer = signers.get(getDefaultSignerKeyId());
try {
jwt.sign(signer);
} catch (JOSEException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
jwt.sign(signer);
} catch (JOSEException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public boolean validateSignature(SignedJWT jwt) {
@ -228,9 +228,9 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
return true;
}
} catch (JOSEException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return false;
}
@ -238,37 +238,37 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
@Override
public Map<String, JWK> getAllPublicKeys() {
Map<String, JWK> pubKeys = new HashMap<String, JWK>();
// pull all keys out of the verifiers if we know how
for (String keyId : keys.keySet()) {
JWK key = keys.get(keyId);
JWK pub = key.toPublicJWK();
if (pub != null) {
pubKeys.put(keyId, pub);
}
}
JWK key = keys.get(keyId);
JWK pub = key.toPublicJWK();
if (pub != null) {
pubKeys.put(keyId, pub);
}
}
return pubKeys;
}
/* (non-Javadoc)
* @see org.mitre.jwt.signer.service.JwtSigningAndValidationService#getAllSigningAlgsSupported()
*/
@Override
public Collection<JWSAlgorithm> getAllSigningAlgsSupported() {
Set<JWSAlgorithm> algs = new HashSet<JWSAlgorithm>();
for (JWSSigner signer : signers.values()) {
algs.addAll(signer.supportedAlgorithms());
}
@Override
public Collection<JWSAlgorithm> getAllSigningAlgsSupported() {
Set<JWSAlgorithm> algs = new HashSet<JWSAlgorithm>();
for (JWSSigner signer : signers.values()) {
algs.addAll(signer.supportedAlgorithms());
}
for (JWSVerifier verifier : verifiers.values()) {
algs.addAll(verifier.supportedAlgorithms());
}
return algs;
}
for (JWSVerifier verifier : verifiers.values()) {
algs.addAll(verifier.supportedAlgorithms());
}
return algs;
}
}

View File

@ -3,12 +3,6 @@
*/
package org.mitre.jwt.signer.service.impl;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPublicKeySpec;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.apache.http.client.HttpClient;
@ -21,19 +15,14 @@ import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jose.jwk.JWK;
import com.google.common.cache.LoadingCache;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.KeyType;
import com.nimbusds.jose.jwk.RSAKey;
/**
*
* Creates a caching map of JOSE signers and validators keyed on the JWK Set URI.
* Creates a caching map of JOSE signers and validators keyed on the JWK Set URI.
* Dynamically loads JWK Sets to create the signing and validation services.
*
* @author jricher
@ -43,7 +32,7 @@ import com.nimbusds.jose.jwk.RSAKey;
public class JWKSetSigningAndValidationServiceCacheService {
private static Logger logger = LoggerFactory.getLogger(JWKSetSigningAndValidationServiceCacheService.class);
// map of jwk set uri -> signing/validation service built on the keys found in that jwk set
private LoadingCache<String, JwtSigningAndValidationService> cache;
@ -52,48 +41,48 @@ public class JWKSetSigningAndValidationServiceCacheService {
.maximumSize(100)
.build(new JWKSetVerifierFetcher());
}
/**
* @param jwksUri
* @return
* @throws ExecutionException
* @see com.google.common.cache.Cache#get(java.lang.Object)
*/
public JwtSigningAndValidationService get(String jwksUri) {
try {
return cache.get(jwksUri);
} catch (ExecutionException e) {
logger.warn("Couldn't load JWK Set from " + jwksUri, e);
return null;
}
}
public JwtSigningAndValidationService get(String jwksUri) {
try {
return cache.get(jwksUri);
} catch (ExecutionException e) {
logger.warn("Couldn't load JWK Set from " + jwksUri, e);
return null;
}
}
/**
* @author jricher
*
*/
private class JWKSetVerifierFetcher extends CacheLoader<String, JwtSigningAndValidationService> {
private HttpClient httpClient = new DefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private RestTemplate restTemplate = new RestTemplate(httpFactory);
/**
* Load the JWK Set and build the appropriate signing service.
*/
@Override
public JwtSigningAndValidationService load(String key) throws Exception {
* @author jricher
*
*/
private class JWKSetVerifierFetcher extends CacheLoader<String, JwtSigningAndValidationService> {
private HttpClient httpClient = new DefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private RestTemplate restTemplate = new RestTemplate(httpFactory);
String jsonString = restTemplate.getForObject(key, String.class);
JWKSet jwkSet = JWKSet.parse(jsonString);
JWKSetKeyStore keyStore = new JWKSetKeyStore(jwkSet);
JwtSigningAndValidationService service = new DefaultJwtSigningAndValidationService(keyStore);
/**
* Load the JWK Set and build the appropriate signing service.
*/
@Override
public JwtSigningAndValidationService load(String key) throws Exception {
return service;
}
String jsonString = restTemplate.getForObject(key, String.class);
JWKSet jwkSet = JWKSet.parse(jsonString);
}
JWKSetKeyStore keyStore = new JWKSetKeyStore(jwkSet);
JwtSigningAndValidationService service = new DefaultJwtSigningAndValidationService(keyStore);
return service;
}
}
}

View File

@ -22,13 +22,13 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication;
public class AuthenticationHolderEntity {
private Long id;
private Long ownerId;
private OAuth2Authentication authentication;
public AuthenticationHolderEntity() {
}
@Id
@ -60,7 +60,7 @@ public class AuthenticationHolderEntity {
public void setAuthentication(OAuth2Authentication authentication) {
this.authentication = authentication;
}
}

View File

@ -28,18 +28,18 @@ import org.springframework.security.oauth2.provider.code.AuthorizationRequestHol
public class AuthorizationCodeEntity {
private Long id;
private String code;
private AuthorizationRequestHolder authorizationRequestHolder;
/**
* Default constructor.
*/
public AuthorizationCodeEntity() {
}
/**
* Create a new AuthorizationCodeEntity with the given code and AuthorizationRequestHolder.
*
@ -50,12 +50,12 @@ public class AuthorizationCodeEntity {
this.code = code;
this.authorizationRequestHolder = authRequest;
}
/**
* @return the id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
@ -98,5 +98,5 @@ public class AuthorizationCodeEntity {
public void setAuthorizationRequestHolder(AuthorizationRequestHolder authorizationRequestHolder) {
this.authorizationRequestHolder = authorizationRequestHolder;
}
}

View File

@ -67,7 +67,7 @@ public class ClientDetailsEntity implements ClientDetails {
private static final long serialVersionUID = -1617727085733786296L;
private Long id;
/** Fields from the OAuth2 Dynamic Registration Specification */
private String clientId = null; // client_id
private String clientSecret = null; // client_secret
@ -75,7 +75,7 @@ public class ClientDetailsEntity implements ClientDetails {
private String clientName; // client_name
private String clientUri; // client_uri
private String logoUri; // logo_uri
private Set<String> contacts; // contacts
private Set<String> contacts; // contacts
private String tosUri; // tos_uri
private AuthMethod tokenEndpointAuthMethod = AuthMethod.SECRET_BASIC; // token_endpoint_auth_method
private Set<String> scope = new HashSet<String>(); // scope
@ -83,38 +83,38 @@ public class ClientDetailsEntity implements ClientDetails {
private Set<String> responseTypes = new HashSet<String>(); // response_types
private String policyUri;
private String jwksUri;
/** Fields from OIDC Client Registration Specification **/
/** Fields from OIDC Client Registration Specification **/
private AppType applicationType; // application_type
private String sectorIdentifierUri; // sector_identifier_uri
private SubjectType subjectType; // subject_type
private JWSAlgorithmEmbed requestObjectSigningAlg = JWSAlgorithmEmbed.NONE; // request_object_signing_alg
private JWSAlgorithmEmbed userInfoSignedResponseAlg = JWSAlgorithmEmbed.NONE; // user_info_signed_response_alg
private JWEAlgorithmEmbed userInfoEncryptedResponseAlg = JWEAlgorithmEmbed.NONE; // user_info_encrypted_response_alg
private JWEEncryptionMethodEmbed userInfoEncryptedResponseEnc = JWEEncryptionMethodEmbed.NONE; // user_info_encrypted_response_enc
private JWSAlgorithmEmbed idTokenSignedResponseAlg = JWSAlgorithmEmbed.NONE; // id_token_signed_response_alg
private JWEAlgorithmEmbed idTokenEncryptedResponseAlg = JWEAlgorithmEmbed.NONE; // id_token_encrypted_response_alg
private JWEEncryptionMethodEmbed idTokenEncryptedResponseEnc = JWEEncryptionMethodEmbed.NONE; // id_token_encrypted_response_enc
private Integer defaultMaxAge; // default_max_age
private Boolean requireAuthTime; // require_auth_time
private Set<String> defaultACRvalues; // default_acr_values
private String initiateLoginUri; // initiate_login_uri
private String postLogoutRedirectUri; // post_logout_redirect_uri
private Set<String> requestUris; // request_uris
/** Fields to support the ClientDetails interface **/
private Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
private Integer accessTokenValiditySeconds = 0; // in seconds
private Integer refreshTokenValiditySeconds = 0; // in seconds
private Integer accessTokenValiditySeconds = 0; // in seconds
private Integer refreshTokenValiditySeconds = 0; // in seconds
private Set<String> resourceIds = new HashSet<String>();
private Map<String, Object> additionalInformation = new HashMap<String, Object>();
/** Our own fields **/
private String clientDescription = ""; // human-readable description
private boolean reuseRefreshToken = true; // do we let someone reuse a refresh token?
@ -122,16 +122,16 @@ public class ClientDetailsEntity implements ClientDetails {
private boolean allowIntrospection = false; // do we let this client call the introspection endpoint?
private Integer idTokenValiditySeconds; //timeout for id tokens
private Date createdAt; // time the client was created
public enum AuthMethod {
SECRET_POST("client_secret_post"),
SECRET_BASIC("client_secret_basic"),
SECRET_JWT("client_secret_jwt"),
PRIVATE_KEY("private_key_jwt"),
SECRET_POST("client_secret_post"),
SECRET_BASIC("client_secret_basic"),
SECRET_JWT("client_secret_jwt"),
PRIVATE_KEY("private_key_jwt"),
NONE("none");
private final String value;
// map to aid reverse lookup
private static final Map<String, AuthMethod> lookup = new HashMap<String, AuthMethod>();
static {
@ -139,77 +139,77 @@ public class ClientDetailsEntity implements ClientDetails {
lookup.put(a.getValue(), a);
}
}
AuthMethod(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public static AuthMethod getByValue(String value) {
return lookup.get(value);
}
}
public enum AppType {
WEB("web"), NATIVE("native");
private final String value;
// map to aid reverse lookup
// map to aid reverse lookup
private static final Map<String, AppType> lookup = new HashMap<String, AppType>();
static {
for (AppType a : AppType.values()) {
lookup.put(a.getValue(), a);
}
lookup.put(a.getValue(), a);
}
}
AppType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public static AppType getByValue(String value) {
return lookup.get(value);
}
}
public enum SubjectType {
PAIRWISE("pairwise"), PUBLIC("public");
public enum SubjectType {
PAIRWISE("pairwise"), PUBLIC("public");
private final String value;
// map to aid reverse lookup
// map to aid reverse lookup
private static final Map<String, SubjectType> lookup = new HashMap<String, SubjectType>();
static {
for (SubjectType u : SubjectType.values()) {
lookup.put(u.getValue(), u);
}
lookup.put(u.getValue(), u);
}
}
SubjectType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public static SubjectType getByValue(String value) {
return lookup.get(value);
}
}
}
/**
* Create a blank ClientDetailsEntity
*/
public ClientDetailsEntity() {
}
/**
@ -228,34 +228,34 @@ public class ClientDetailsEntity implements ClientDetails {
public void setId(Long id) {
this.id = id;
}
/**
* @return the clientDescription
*/
* @return the clientDescription
*/
@Basic
@Column(name="client_description")
public String getClientDescription() {
return clientDescription;
}
public String getClientDescription() {
return clientDescription;
}
/**
* @param clientDescription Human-readable long description of the client (optional)
*/
public void setClientDescription(String clientDescription) {
this.clientDescription = clientDescription;
}
* @param clientDescription Human-readable long description of the client (optional)
*/
public void setClientDescription(String clientDescription) {
this.clientDescription = clientDescription;
}
/**
* @return the allowRefresh
*/
* @return the allowRefresh
*/
@Transient
public boolean isAllowRefresh() {
public boolean isAllowRefresh() {
if (grantTypes != null) {
return getAuthorizedGrantTypes().contains("refresh_token");
} else {
return false; // if there are no grants, we can't be refreshing them, can we?
}
}
}
@Basic
@Column(name="reuse_refresh_tokens")
@ -266,7 +266,7 @@ public class ClientDetailsEntity implements ClientDetails {
public void setReuseRefreshToken(boolean reuseRefreshToken) {
this.reuseRefreshToken = reuseRefreshToken;
}
/**
* @return the idTokenValiditySeconds
*/
@ -282,7 +282,7 @@ public class ClientDetailsEntity implements ClientDetails {
public void setIdTokenValiditySeconds(Integer idTokenValiditySeconds) {
this.idTokenValiditySeconds = idTokenValiditySeconds;
}
/**
* @return the dynamicallyRegistered
*/
@ -298,148 +298,149 @@ public class ClientDetailsEntity implements ClientDetails {
public void setDynamicallyRegistered(boolean dynamicallyRegistered) {
this.dynamicallyRegistered = dynamicallyRegistered;
}
/**
* @return the allowIntrospection
*/
* @return the allowIntrospection
*/
@Basic
@Column(name="allow_introspection")
public boolean isAllowIntrospection() {
return allowIntrospection;
}
public boolean isAllowIntrospection() {
return allowIntrospection;
}
/**
* @param allowIntrospection the allowIntrospection to set
*/
public void setAllowIntrospection(boolean allowIntrospection) {
this.allowIntrospection = allowIntrospection;
}
* @param allowIntrospection the allowIntrospection to set
*/
public void setAllowIntrospection(boolean allowIntrospection) {
this.allowIntrospection = allowIntrospection;
}
/**
*
*/
@Override
@Transient
public boolean isSecretRequired() {
// TODO: this should check the auth method field instead
return getClientSecret() != null;
}
*/
@Override
@Transient
public boolean isSecretRequired() {
// TODO: this should check the auth method field instead
return getClientSecret() != null;
}
/**
* If the scope list is not null or empty, then this client has been scoped.
*/
@Override
@Transient
public boolean isScoped() {
return getScope() != null && !getScope().isEmpty();
}
*/
@Override
@Transient
public boolean isScoped() {
return getScope() != null && !getScope().isEmpty();
}
/**
* @return the clientId
*/
* @return the clientId
*/
@Basic
@Override
@Column(name="client_id")
public String getClientId() {
return clientId;
}
public String getClientId() {
return clientId;
}
/**
* @param clientId The OAuth2 client_id, must be unique to this client
*/
public void setClientId(String clientId) {
this.clientId = clientId;
}
* @param clientId The OAuth2 client_id, must be unique to this client
*/
public void setClientId(String clientId) {
this.clientId = clientId;
}
/**
* @return the clientSecret
*/
* @return the clientSecret
*/
@Basic
@Override
@Column(name="client_secret")
public String getClientSecret() {
return clientSecret;
}
return clientSecret;
}
/**
* @param clientSecret the OAuth2 client_secret (optional)
*/
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
* @param clientSecret the OAuth2 client_secret (optional)
*/
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
/**
* @return the scope
*/
* @return the scope
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="client_scope",
joinColumns=@JoinColumn(name="owner_id")
)
)
@Override
@Column(name="scope")
public Set<String> getScope() {
return scope;
}
return scope;
}
/**
* @param scope the set of scopes allowed to be issued to this client
*/
public void setScope(Set<String> scope) {
this.scope = scope;
}
* @param scope the set of scopes allowed to be issued to this client
*/
public void setScope(Set<String> scope) {
this.scope = scope;
}
/**
* @return the authorizedGrantTypes
*/
* @return the authorizedGrantTypes
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="client_grant_type",
joinColumns=@JoinColumn(name="owner_id")
)
)
@Column(name="grant_type")
public Set<String> getGrantTypes() {
return grantTypes;
}
return grantTypes;
}
/**
* @param authorizedGrantTypes the OAuth2 grant types that this client is allowed to use
*/
public void setGrantTypes(Set<String> grantTypes) {
this.grantTypes = grantTypes;
}
* @param authorizedGrantTypes the OAuth2 grant types that this client is allowed to use
*/
public void setGrantTypes(Set<String> grantTypes) {
this.grantTypes = grantTypes;
}
/**
* passthrough for SECOAUTH api
*/
public Set<String> getAuthorizedGrantTypes() {
return getGrantTypes();
}
/**
* @return the authorities
*/
* passthrough for SECOAUTH api
*/
@Override
public Set<String> getAuthorizedGrantTypes() {
return getGrantTypes();
}
/**
* @return the authorities
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="client_authority",
joinColumns=@JoinColumn(name="owner_id")
)
)
@Override
@Column(name="authority")
public Set<GrantedAuthority> getAuthorities() {
return authorities;
}
public Set<GrantedAuthority> getAuthorities() {
return authorities;
}
/**
* @param authorities the Spring Security authorities this client is given
*/
public void setAuthorities(Set<GrantedAuthority> authorities) {
this.authorities = authorities;
}
* @param authorities the Spring Security authorities this client is given
*/
public void setAuthorities(Set<GrantedAuthority> authorities) {
this.authorities = authorities;
}
@Override
@Basic
@ -447,13 +448,13 @@ public class ClientDetailsEntity implements ClientDetails {
public Integer getAccessTokenValiditySeconds() {
return accessTokenValiditySeconds;
}
/**
* @param accessTokenTimeout the accessTokenTimeout to set
*/
public void setAccessTokenValiditySeconds(Integer accessTokenValiditySeconds) {
this.accessTokenValiditySeconds = accessTokenValiditySeconds;
}
* @param accessTokenTimeout the accessTokenTimeout to set
*/
public void setAccessTokenValiditySeconds(Integer accessTokenValiditySeconds) {
this.accessTokenValiditySeconds = accessTokenValiditySeconds;
}
@Override
@Basic
@ -461,64 +462,65 @@ public class ClientDetailsEntity implements ClientDetails {
public Integer getRefreshTokenValiditySeconds() {
return refreshTokenValiditySeconds;
}
/**
* @param refreshTokenTimeout Lifetime of refresh tokens, in seconds (optional - leave null for no timeout)
*/
public void setRefreshTokenValiditySeconds(Integer refreshTokenValiditySeconds) {
this.refreshTokenValiditySeconds = refreshTokenValiditySeconds;
}
/**
* @return the registeredRedirectUri
*/
@ElementCollection(fetch = FetchType.EAGER)
* @param refreshTokenTimeout Lifetime of refresh tokens, in seconds (optional - leave null for no timeout)
*/
public void setRefreshTokenValiditySeconds(Integer refreshTokenValiditySeconds) {
this.refreshTokenValiditySeconds = refreshTokenValiditySeconds;
}
/**
* @return the registeredRedirectUri
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="client_redirect_uri",
joinColumns=@JoinColumn(name="owner_id")
)
@Column(name="redirect_uri")
public Set<String> getRedirectUris() {
return redirectUris;
}
)
@Column(name="redirect_uri")
public Set<String> getRedirectUris() {
return redirectUris;
}
/**
* @param registeredRedirectUri the registeredRedirectUri to set
*/
public void setRedirectUris(Set<String> redirectUris) {
this.redirectUris = redirectUris;
}
* @param registeredRedirectUri the registeredRedirectUri to set
*/
public void setRedirectUris(Set<String> redirectUris) {
this.redirectUris = redirectUris;
}
/**
* Pass-through method to fulfill the ClientDetails interface with a bad name
*/
@Override
@Transient
public Set<String> getRegisteredRedirectUri() {
return getRedirectUris();
}
/**
* @return the resourceIds
*/
* Pass-through method to fulfill the ClientDetails interface with a bad name
*/
@Override
@Transient
public Set<String> getRegisteredRedirectUri() {
return getRedirectUris();
}
/**
* @return the resourceIds
*/
@Override
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="client_resource",
joinColumns=@JoinColumn(name="owner_id")
)
)
@Column(name="resource_id")
public Set<String> getResourceIds() {
return resourceIds;
}
public Set<String> getResourceIds() {
return resourceIds;
}
/**
* @param resourceIds the resourceIds to set
*/
public void setResourceIds(Set<String> resourceIds) {
this.resourceIds = resourceIds;
}
* @param resourceIds the resourceIds to set
*/
public void setResourceIds(Set<String> resourceIds) {
this.resourceIds = resourceIds;
}
/**
* This library does not make use of this field, so it is not
* stored using our persistence layer.
@ -533,7 +535,7 @@ public class ClientDetailsEntity implements ClientDetails {
return this.additionalInformation;
}
@Enumerated(EnumType.STRING)
@ -580,7 +582,7 @@ public class ClientDetailsEntity implements ClientDetails {
@CollectionTable(
name="client_contact",
joinColumns=@JoinColumn(name="owner_id")
)
)
@Column(name="contact")
public Set<String> getContacts() {
return contacts;
@ -599,7 +601,7 @@ public class ClientDetailsEntity implements ClientDetails {
public void setLogoUri(String logoUri) {
this.logoUri = logoUri;
}
@Basic
@Column(name="policy_uri")
public String getPolicyUri() {
@ -611,36 +613,36 @@ public class ClientDetailsEntity implements ClientDetails {
}
/**
* @return the clientUrl
*/
* @return the clientUrl
*/
@Basic
@Column(name="client_uri")
public String getClientUri() {
return clientUri;
}
public String getClientUri() {
return clientUri;
}
/**
* @param clientUrl the clientUrl to set
*/
public void setClientUri(String clientUri) {
this.clientUri = clientUri;
}
* @param clientUrl the clientUrl to set
*/
public void setClientUri(String clientUri) {
this.clientUri = clientUri;
}
/**
* @return the tosUrl
*/
@Basic
@Column(name="tos_uri")
public String getTosUri() {
return tosUri;
}
* @return the tosUrl
*/
@Basic
@Column(name="tos_uri")
public String getTosUri() {
return tosUri;
}
/**
* @param tosUrl the tosUrl to set
*/
public void setTosUri(String tosUri) {
this.tosUri = tosUri;
}
* @param tosUrl the tosUrl to set
*/
public void setTosUri(String tosUri) {
this.tosUri = tosUri;
}
@Basic
@Column(name="jwks_uri")
@ -708,7 +710,7 @@ public class ClientDetailsEntity implements ClientDetails {
public void setUserInfoEncryptedResponseEnc(JWEEncryptionMethodEmbed userInfoEncryptedResponseEnc) {
this.userInfoEncryptedResponseEnc = userInfoEncryptedResponseEnc;
}
}
@Embedded
@AttributeOverrides({
@ -773,7 +775,7 @@ public class ClientDetailsEntity implements ClientDetails {
@CollectionTable(
name="client_response_type",
joinColumns=@JoinColumn(name="response_type")
)
)
@Column(name="response_type")
public Set<String> getResponseTypes() {
return responseTypes;
@ -793,7 +795,7 @@ public class ClientDetailsEntity implements ClientDetails {
@CollectionTable(
name="client_default_acr_value",
joinColumns=@JoinColumn(name="owner_id")
)
)
@Column(name="default_acr_value")
public Set<String> getDefaultACRvalues() {
return defaultACRvalues;
@ -845,7 +847,7 @@ public class ClientDetailsEntity implements ClientDetails {
@CollectionTable(
name="client_request_uri",
joinColumns=@JoinColumn(name="owner_id")
)
)
@Column(name="request_uri")
public Set<String> getRequestUris() {
return requestUris;
@ -863,15 +865,15 @@ public class ClientDetailsEntity implements ClientDetails {
*/
@Temporal(TemporalType.TIMESTAMP)
@Column(name="created_at")
public Date getCreatedAt() {
return createdAt;
}
public Date getCreatedAt() {
return createdAt;
}
/**
* @param createdAt the createdAt to set
*/
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
}

View File

@ -47,9 +47,7 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.JWTParser;
import com.nimbusds.jwt.PlainJWT;
/**
* @author jricher
@ -73,17 +71,17 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
public static final String REGISTRATION_TOKEN_SCOPE = "registration-token";
public static String ID_TOKEN = "id_token";
private Long id;
private ClientDetailsEntity client;
private AuthenticationHolderEntity authenticationHolder; // the authentication that made this access
private JWT jwtValue; // JWT-encoded access token value
private OAuth2AccessTokenEntity idToken; // JWT-encoded OpenID Connect IdToken
private Date expiration;
private String tokenType = OAuth2AccessToken.BEARER_TYPE;
@ -91,14 +89,14 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
private OAuth2RefreshTokenEntity refreshToken;
private Set<String> scope;
/**
* Create a new, blank access token
*/
public OAuth2AccessTokenEntity() {
}
/**
* @return the id
*/
@ -116,8 +114,9 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
}
/**
* Get all additional information to be sent to the serializer. Inserts a copy of the IdToken (in JWT String form).
* Get all additional information to be sent to the serializer. Inserts a copy of the IdToken (in JWT String form).
*/
@Override
@Transient
public Map<String, Object> getAdditionalInformation() {
Map<String, Object> map = new HashMap<String, Object>(); //super.getAdditionalInformation();
@ -126,121 +125,127 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
}
return map;
}
/**
* The authentication in place when this token was created.
* @return the authentication
*/
* @return the authentication
*/
@ManyToOne
@JoinColumn(name = "auth_holder_id")
public AuthenticationHolderEntity getAuthenticationHolder() {
return authenticationHolder;
}
public AuthenticationHolderEntity getAuthenticationHolder() {
return authenticationHolder;
}
/**
* @param authentication the authentication to set
*/
public void setAuthenticationHolder(AuthenticationHolderEntity authenticationHolder) {
this.authenticationHolder = authenticationHolder;
}
* @param authentication the authentication to set
*/
public void setAuthenticationHolder(AuthenticationHolderEntity authenticationHolder) {
this.authenticationHolder = authenticationHolder;
}
/**
* @return the client
*/
* @return the client
*/
@ManyToOne
@JoinColumn(name = "client_id")
public ClientDetailsEntity getClient() {
return client;
}
public ClientDetailsEntity getClient() {
return client;
}
/**
* @param client the client to set
*/
public void setClient(ClientDetailsEntity client) {
this.client = client;
}
/**
* Get the string-encoded value of this access token.
*/
@Basic
@Column(name="token_value")
public String getValue() {
return jwtValue.serialize();
}
* @param client the client to set
*/
public void setClient(ClientDetailsEntity client) {
this.client = client;
}
/**
* Set the "value" of this Access Token
*
* @param value the JWT string
* @throws ParseException if "value" is not a properly formatted JWT string
*/
public void setValue(String value) throws ParseException {
setJwt(JWTParser.parse(value));
}
/**
* Get the string-encoded value of this access token.
*/
@Override
@Basic
@Column(name="token_value")
public String getValue() {
return jwtValue.serialize();
}
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
public Date getExpiration() {
return expiration;
}
/**
* Set the "value" of this Access Token
*
* @param value the JWT string
* @throws ParseException if "value" is not a properly formatted JWT string
*/
public void setValue(String value) throws ParseException {
setJwt(JWTParser.parse(value));
}
public void setExpiration(Date expiration) {
this.expiration = expiration;
}
@Override
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
public Date getExpiration() {
return expiration;
}
@Basic
@Column(name="token_type")
public String getTokenType() {
return tokenType;
}
public void setExpiration(Date expiration) {
this.expiration = expiration;
}
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}
@Override
@Basic
@Column(name="token_type")
public String getTokenType() {
return tokenType;
}
@ManyToOne
@JoinColumn(name="refresh_token_id")
public OAuth2RefreshTokenEntity getRefreshToken() {
return refreshToken;
}
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}
public void setRefreshToken(OAuth2RefreshTokenEntity refreshToken) {
this.refreshToken = refreshToken;
}
@Override
@ManyToOne
@JoinColumn(name="refresh_token_id")
public OAuth2RefreshTokenEntity getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(OAuth2RefreshToken refreshToken) {
if (!(refreshToken instanceof OAuth2RefreshTokenEntity)) {
// TODO: make a copy constructor instead....
throw new IllegalArgumentException("Not a storable refresh token entity!");
}
// force a pass through to the entity version
setRefreshToken((OAuth2RefreshTokenEntity)refreshToken);
}
@ElementCollection(fetch=FetchType.EAGER)
@CollectionTable(
joinColumns=@JoinColumn(name="owner_id"),
name="token_scope"
)
public Set<String> getScope() {
return scope;
}
public void setRefreshToken(OAuth2RefreshTokenEntity refreshToken) {
this.refreshToken = refreshToken;
}
public void setScope(Set<String> scope) {
this.scope = scope;
}
public void setRefreshToken(OAuth2RefreshToken refreshToken) {
if (!(refreshToken instanceof OAuth2RefreshTokenEntity)) {
// TODO: make a copy constructor instead....
throw new IllegalArgumentException("Not a storable refresh token entity!");
}
// force a pass through to the entity version
setRefreshToken((OAuth2RefreshTokenEntity)refreshToken);
}
@Transient
@Override
@ElementCollection(fetch=FetchType.EAGER)
@CollectionTable(
joinColumns=@JoinColumn(name="owner_id"),
name="token_scope"
)
public Set<String> getScope() {
return scope;
}
public void setScope(Set<String> scope) {
this.scope = scope;
}
@Override
@Transient
public boolean isExpired() {
return getExpiration() == null ? false : System.currentTimeMillis() > getExpiration().getTime();
}
/**
* @return the idToken
*/
@OneToOne(cascade=CascadeType.ALL) // one-to-one mapping for now
@JoinColumn(name = "id_token_id")
@OneToOne(cascade=CascadeType.ALL) // one-to-one mapping for now
@JoinColumn(name = "id_token_id")
public OAuth2AccessTokenEntity getIdToken() {
return idToken;
}
@ -251,7 +256,7 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
public void setIdToken(OAuth2AccessTokenEntity idToken) {
this.idToken = idToken;
}
/**
* @return the idTokenString
*/

View File

@ -39,9 +39,7 @@ import javax.persistence.Transient;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.JWTParser;
import com.nimbusds.jwt.PlainJWT;
/**
* @author jricher
@ -58,14 +56,14 @@ import com.nimbusds.jwt.PlainJWT;
public class OAuth2RefreshTokenEntity implements OAuth2RefreshToken {
private Long id;
private AuthenticationHolderEntity authenticationHolder;
private ClientDetailsEntity client;
//JWT-encoded representation of this access token entity
private JWT jwt;
// our refresh tokens might expire
private Date expiration;
@ -91,97 +89,98 @@ public class OAuth2RefreshTokenEntity implements OAuth2RefreshToken {
public void setId(Long id) {
this.id = id;
}
/**
* The authentication in place when the original access token was
* created
*
* @return the authentication
*/
@ManyToOne
@JoinColumn(name = "auth_holder_id")
public AuthenticationHolderEntity getAuthenticationHolder() {
return authenticationHolder;
}
/**
* @param authentication the authentication to set
*/
public void setAuthenticationHolder(AuthenticationHolderEntity authenticationHolder) {
this.authenticationHolder = authenticationHolder;
}
* The authentication in place when the original access token was
* created
*
* @return the authentication
*/
@ManyToOne
@JoinColumn(name = "auth_holder_id")
public AuthenticationHolderEntity getAuthenticationHolder() {
return authenticationHolder;
}
/**
* @param authentication the authentication to set
*/
public void setAuthenticationHolder(AuthenticationHolderEntity authenticationHolder) {
this.authenticationHolder = authenticationHolder;
}
/**
* Get the JWT-encoded value of this token
*/
@Basic
@Column(name="token_value")
public String getValue() {
return jwt.serialize();
}
@Override
@Basic
@Column(name="token_value")
public String getValue() {
return jwt.serialize();
}
/**
* Set the value of this token as a string. Parses the string into a JWT.
* @param value
* @throws ParseException if the value is not a valid JWT string
*/
public void setValue(String value) throws ParseException {
setJwt(JWTParser.parse(value));
}
/**
* Set the value of this token as a string. Parses the string into a JWT.
* @param value
* @throws ParseException if the value is not a valid JWT string
*/
public void setValue(String value) throws ParseException {
setJwt(JWTParser.parse(value));
}
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
public Date getExpiration() {
return expiration;
}
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
public Date getExpiration() {
return expiration;
}
/* (non-Javadoc)
* @see org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken#setExpiration(java.util.Date)
*/
public void setExpiration(Date expiration) {
this.expiration = expiration;
}
* @see org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken#setExpiration(java.util.Date)
*/
/**
* Has this token expired?
* @return true if it has a timeout set and the timeout has passed
*/
@Transient
public void setExpiration(Date expiration) {
this.expiration = expiration;
}
/**
* Has this token expired?
* @return true if it has a timeout set and the timeout has passed
*/
@Transient
public boolean isExpired() {
return getExpiration() == null ? false : System.currentTimeMillis() > getExpiration().getTime();
}
/**
* @return the client
*/
* @return the client
*/
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "client_id")
public ClientDetailsEntity getClient() {
return client;
}
public ClientDetailsEntity getClient() {
return client;
}
/**
* @param client the client to set
*/
public void setClient(ClientDetailsEntity client) {
this.client = client;
}
* @param client the client to set
*/
public void setClient(ClientDetailsEntity client) {
this.client = client;
}
/**
* Get the JWT object directly
* @return the jwt
*/
@Transient
public JWT getJwt() {
return jwt;
}
/**
* @param jwt the jwt to set
*/
public void setJwt(JWT jwt) {
this.jwt = jwt;
}
/**
* Get the JWT object directly
* @return the jwt
*/
@Transient
public JWT getJwt() {
return jwt;
}
/**
* @param jwt the jwt to set
*/
public void setJwt(JWT jwt) {
this.jwt = jwt;
}
}

View File

@ -28,7 +28,7 @@ public class SystemScope {
private Long id;
private String value; // scope value
private String description; // human-readable description
private String icon; // class of the icon to display on the auth page
private String icon; // class of the icon to display on the auth page
private boolean allowDynReg = false; // can a dynamically registered client ask for this scope?
private boolean defaultScope = false; // is this a default scope for newly-registered clients?
@ -36,16 +36,16 @@ public class SystemScope {
* Make a blank system scope with no value
*/
public SystemScope() {
}
/**
* Make a system scope with the given scope value
* @param value
*/
public SystemScope(String value) {
this.value = value;
}
public SystemScope(String value) {
this.value = value;
}
/**
* @return the id
*/
@ -117,7 +117,7 @@ public class SystemScope {
public void setAllowDynReg(boolean allowDynReg) {
this.allowDynReg = allowDynReg;
}
/**
* @return the defaultScope
*/
@ -136,76 +136,76 @@ public class SystemScope {
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (allowDynReg ? 1231 : 1237);
result = prime * result + (defaultScope ? 1231 : 1237);
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((icon == null) ? 0 : icon.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (allowDynReg ? 1231 : 1237);
result = prime * result + (defaultScope ? 1231 : 1237);
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((icon == null) ? 0 : icon.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
SystemScope other = (SystemScope) obj;
if (allowDynReg != other.allowDynReg) {
return false;
}
if (defaultScope != other.defaultScope) {
return false;
}
if (description == null) {
if (other.description != null) {
return false;
}
} else if (!description.equals(other.description)) {
return false;
}
if (icon == null) {
if (other.icon != null) {
return false;
}
} else if (!icon.equals(other.icon)) {
return false;
}
if (id == null) {
if (other.id != null) {
return false;
}
} else if (!id.equals(other.id)) {
return false;
}
if (value == null) {
if (other.value != null) {
return false;
}
} else if (!value.equals(other.value)) {
return false;
}
return true;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
SystemScope other = (SystemScope) obj;
if (allowDynReg != other.allowDynReg) {
return false;
}
if (defaultScope != other.defaultScope) {
return false;
}
if (description == null) {
if (other.description != null) {
return false;
}
} else if (!description.equals(other.description)) {
return false;
}
if (icon == null) {
if (other.icon != null) {
return false;
}
} else if (!icon.equals(other.icon)) {
return false;
}
if (id == null) {
if (other.id != null) {
return false;
}
} else if (!id.equals(other.id)) {
return false;
}
if (value == null) {
if (other.value != null) {
return false;
}
} else if (!value.equals(other.value)) {
return false;
}
return true;
}
@Override
public String toString() {
return "SystemScope [value=" + value + ", description=" + description + ", icon=" + icon + ", allowDynReg=" + allowDynReg + ", defaultScope=" + defaultScope + "]";
}
@Override
public String toString() {
return "SystemScope [value=" + value + ", description=" + description + ", icon=" + icon + ", allowDynReg=" + allowDynReg + ", defaultScope=" + defaultScope + "]";
}
}

View File

@ -6,13 +6,13 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication;
public interface AuthenticationHolderRepository {
public AuthenticationHolderEntity getById(Long id);
public AuthenticationHolderEntity getByAuthentication(OAuth2Authentication a);
public void removeById(Long id);
public void remove(AuthenticationHolderEntity a);
public AuthenticationHolderEntity save(AuthenticationHolderEntity a);
}

View File

@ -5,7 +5,7 @@ import org.springframework.security.oauth2.common.exceptions.InvalidGrantExcepti
import org.springframework.security.oauth2.provider.code.AuthorizationRequestHolder;
/**
* Interface for saving and consuming OAuth2 authorization codes as AuthorizationCodeEntitys.
* Interface for saving and consuming OAuth2 authorization codes as AuthorizationCodeEntitys.
*
* @author aanganes
*
@ -19,14 +19,14 @@ public interface AuthorizationCodeRepository {
* @return the saved AuthorizationCodeEntity
*/
public AuthorizationCodeEntity save(AuthorizationCodeEntity authorizationCode);
/**
* Consume an authorization code.
*
* @param code the authorization code value
* @return the authentication associated with the code
* @return the authentication associated with the code
* @throws InvalidGrantException if no AuthorizationCodeEntity is found with the given value
*/
public AuthorizationRequestHolder consume(String code) throws InvalidGrantException;
}

View File

@ -20,7 +20,7 @@ import java.util.Collection;
import org.mitre.oauth2.model.ClientDetailsEntity;
public interface OAuth2ClientRepository {
public ClientDetailsEntity getById(Long id);
public ClientDetailsEntity getClientByClientId(String clientId);

View File

@ -27,17 +27,17 @@ public interface OAuth2TokenRepository {
public OAuth2AccessTokenEntity saveAccessToken(OAuth2AccessTokenEntity token);
public OAuth2RefreshTokenEntity getRefreshTokenByValue(String refreshTokenValue);
public OAuth2RefreshTokenEntity getRefreshTokenById(Long Id);
public void clearAccessTokensForRefreshToken(OAuth2RefreshTokenEntity refreshToken);
public void removeRefreshToken(OAuth2RefreshTokenEntity refreshToken);
public OAuth2RefreshTokenEntity saveRefreshToken(OAuth2RefreshTokenEntity refreshToken);
public OAuth2AccessTokenEntity getAccessTokenByValue(String accessTokenValue);
public OAuth2AccessTokenEntity getAccessTokenById(Long id);
public void removeAccessToken(OAuth2AccessTokenEntity accessToken);
@ -55,8 +55,8 @@ public interface OAuth2TokenRepository {
public OAuth2AccessTokenEntity getByAuthentication(OAuth2Authentication auth);
/**
* @return
*/
public OAuth2AccessTokenEntity getAccessTokenForIdToken(OAuth2AccessTokenEntity idToken);
* @return
*/
public OAuth2AccessTokenEntity getAccessTokenForIdToken(OAuth2AccessTokenEntity idToken);
}

View File

@ -14,13 +14,13 @@ import org.mitre.oauth2.model.SystemScope;
public interface SystemScopeRepository {
public Set<SystemScope> getAll();
public SystemScope getById(Long id);
public SystemScope getByValue(String value);
public void remove(SystemScope scope);
public SystemScope save(SystemScope scope);
}

View File

@ -24,19 +24,20 @@ import org.springframework.security.oauth2.provider.ClientDetailsService;
public interface ClientDetailsEntityService extends ClientDetailsService {
public ClientDetailsEntity saveNewClient(ClientDetailsEntity client);
public ClientDetailsEntity getClientById(Long id);
@Override
public ClientDetailsEntity loadClientByClientId(String clientId) throws OAuth2Exception;
public void deleteClient(ClientDetailsEntity client);
public ClientDetailsEntity updateClient(ClientDetailsEntity oldClient, ClientDetailsEntity newClient);
public Collection<ClientDetailsEntity> getAllClients();
public ClientDetailsEntity generateClientId(ClientDetailsEntity client);
public ClientDetailsEntity generateClientSecret(ClientDetailsEntity client);
}

View File

@ -26,30 +26,32 @@ import org.springframework.security.oauth2.provider.token.ResourceServerTokenSer
public interface OAuth2TokenEntityService extends AuthorizationServerTokenServices, ResourceServerTokenServices {
@Override
public OAuth2AccessTokenEntity readAccessToken(String accessTokenValue);
public OAuth2RefreshTokenEntity getRefreshToken(String refreshTokenValue);
public void revokeRefreshToken(OAuth2RefreshTokenEntity refreshToken);
public void revokeAccessToken(OAuth2AccessTokenEntity accessToken);
public List<OAuth2AccessTokenEntity> getAccessTokensForClient(ClientDetailsEntity client);
public List<OAuth2RefreshTokenEntity> getRefreshTokensForClient(ClientDetailsEntity client);
public void clearExpiredTokens();
public OAuth2AccessTokenEntity saveAccessToken(OAuth2AccessTokenEntity accessToken);
public OAuth2RefreshTokenEntity saveRefreshToken(OAuth2RefreshTokenEntity refreshToken);
@Override
public OAuth2AccessTokenEntity getAccessToken(OAuth2Authentication authentication);
/**
* @param incomingToken
* @return
*/
public OAuth2AccessTokenEntity getAccessTokenForIdToken(OAuth2AccessTokenEntity idToken);
* @param incomingToken
* @return
*/
public OAuth2AccessTokenEntity getAccessTokenForIdToken(OAuth2AccessTokenEntity idToken);
}

View File

@ -12,15 +12,15 @@ import org.mitre.oauth2.model.SystemScope;
*
*/
public interface SystemScopeService {
public Set<SystemScope> getAll();
/**
* Get all scopes that are defaulted to new clients on this system
* @return
*/
public Set<SystemScope> getDefaults();
/**
* Get all scopes that are allowed for dynamic registration on this system
* @return
@ -28,20 +28,20 @@ public interface SystemScopeService {
public Set<SystemScope> getDynReg();
public SystemScope getById(Long id);
public SystemScope getByValue(String value);
public void remove(SystemScope scope);
public SystemScope save(SystemScope scope);
/**
* Translate the set of scope strings into a set of SystemScope objects.
* @param scope
* @return
*/
public Set<SystemScope> fromStrings(Set<String> scope);
/**
* Pluck the scope values from the set of SystemScope objects and return a list of strings
* @param scope

View File

@ -17,7 +17,6 @@ package org.mitre.oauth2.service.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
@ -44,32 +43,32 @@ public class DefaultClientUserDetailsService implements UserDetailsService {
private ClientDetailsService clientDetailsService;
@Override
public UserDetails loadUserByUsername(String clientId) throws UsernameNotFoundException, DataAccessException {
public UserDetails loadUserByUsername(String clientId) throws UsernameNotFoundException, DataAccessException {
ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
if (client != null) {
String password = client.getClientSecret();
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
Collection<GrantedAuthority> authorities = client.getAuthorities();
if (authorities == null || authorities.isEmpty()) {
// automatically inject ROLE_CLIENT if none exists ...
// TODO: this should probably happen on the client service side instead to keep it in the real data model
authorities = new ArrayList<GrantedAuthority>();
GrantedAuthority roleClient = new SimpleGrantedAuthority("ROLE_CLIENT");
authorities.add(roleClient);
}
return new User(clientId, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
String password = client.getClientSecret();
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
Collection<GrantedAuthority> authorities = client.getAuthorities();
if (authorities == null || authorities.isEmpty()) {
// automatically inject ROLE_CLIENT if none exists ...
// TODO: this should probably happen on the client service side instead to keep it in the real data model
authorities = new ArrayList<GrantedAuthority>();
GrantedAuthority roleClient = new SimpleGrantedAuthority("ROLE_CLIENT");
authorities.add(roleClient);
}
return new User(clientId, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
} else {
throw new UsernameNotFoundException("Client not found: " + clientId);
}
}
}
public ClientDetailsService getClientDetailsService() {
return clientDetailsService;
@ -78,5 +77,5 @@ public class DefaultClientUserDetailsService implements UserDetailsService {
public void setClientDetailsService(ClientDetailsService clientDetailsService) {
this.clientDetailsService = clientDetailsService;
}
}

View File

@ -29,7 +29,7 @@ import com.google.gson.reflect.TypeToken;
*
*/
public class ClientDetailsEntityJsonProcessor {
private static Gson gson = new Gson();
private static JsonParser parser = new JsonParser();
@ -43,16 +43,16 @@ public class ClientDetailsEntityJsonProcessor {
public static ClientDetailsEntity parse(String jsonString) {
JsonElement jsonEl = parser.parse(jsonString);
if (jsonEl.isJsonObject()) {
JsonObject o = jsonEl.getAsJsonObject();
ClientDetailsEntity c = new ClientDetailsEntity();
// TODO: make these field names into constants
// these two fields should only be sent in the update request, and MUST match existing values
c.setClientId(getAsString(o, "client_id"));
c.setClientSecret(getAsString(o, "client_secret"));
// OAuth DynReg
c.setRedirectUris(getAsStringSet(o, "redirect_uris"));
c.setClientName(getAsString(o, "client_name"));
@ -60,66 +60,66 @@ public class ClientDetailsEntityJsonProcessor {
c.setLogoUri(getAsString(o, "logo_uri"));
c.setContacts(getAsStringSet(o, "contacts"));
c.setTosUri(getAsString(o, "tos_uri"));
String authMethod = getAsString(o, "token_endpoint_auth_method");
if (authMethod != null) {
c.setTokenEndpointAuthMethod(AuthMethod.getByValue(authMethod));
}
// scope is a space-separated string
String scope = getAsString(o, "scope");
if (scope != null) {
c.setScope(Sets.newHashSet(Splitter.on(" ").split(scope)));
}
c.setGrantTypes(getAsStringSet(o, "grant_types"));
c.setPolicyUri(getAsString(o, "policy_uri"));
c.setJwksUri(getAsString(o, "jwks_uri"));
// OIDC Additions
String appType = getAsString(o, "application_type");
if (appType != null) {
c.setApplicationType(AppType.getByValue(appType));
}
c.setSectorIdentifierUri(getAsString(o, "sector_identifier_uri"));
String subjectType = getAsString(o, "subject_type");
if (subjectType != null) {
c.setSubjectType(SubjectType.getByValue(subjectType));
}
c.setRequestObjectSigningAlg(getAsJwsAlgorithm(o, "request_object_signing_alg"));
c.setUserInfoSignedResponseAlg(getAsJwsAlgorithm(o, "userinfo_signed_response_alg"));
c.setUserInfoEncryptedResponseAlg(getAsJweAlgorithm(o, "userinfo_encrypted_response_alg"));
c.setUserInfoEncryptedResponseEnc(getAsJweEncryptionMethod(o, "userinfo_encrypted_response_enc"));
c.setIdTokenSignedResponseAlg(getAsJwsAlgorithm(o, "id_token_signed_response_alg"));
c.setIdTokenEncryptedResponseAlg(getAsJweAlgorithm(o, "id_token_encrypted_response_alg"));
c.setIdTokenEncryptedResponseEnc(getAsJweEncryptionMethod(o, "id_token_encrypted_response_enc"));
if (o.has("default_max_age")) {
if (o.get("default_max_age").isJsonPrimitive()) {
c.setDefaultMaxAge(o.get("default_max_age").getAsInt());
}
}
if (o.has("require_auth_time")) {
if (o.get("require_auth_time").isJsonPrimitive()) {
c.setRequireAuthTime(o.get("require_auth_time").getAsBoolean());
}
}
c.setDefaultACRvalues(getAsStringSet(o, "default_acr_values"));
c.setInitiateLoginUri(getAsString(o, "initiate_login_uri"));
c.setPostLogoutRedirectUri(getAsString(o, "post_logout_redirect_uri"));
c.setRequestUris(getAsStringSet(o, "request_uris"));
return c;
} else {
return null;
return null;
}
}
@ -134,28 +134,28 @@ public class ClientDetailsEntityJsonProcessor {
* @return
*/
public static JsonObject serialize(ClientDetailsEntity c, OAuth2AccessTokenEntity token, String registrationUri) {
JsonObject o = new JsonObject();
JsonObject o = new JsonObject();
o.addProperty("client_id", c.getClientId());
if (c.getClientSecret() != null) {
o.addProperty("client_secret", c.getClientSecret());
o.addProperty("expires_at", 0); // TODO: do we want to let secrets expire?
}
if (c.getCreatedAt() != null) {
o.addProperty("issued_at", c.getCreatedAt().getTime());
}
if (token != null) {
o.addProperty("registration_access_token", token.getValue());
}
if (registrationUri != null) {
o.addProperty("registration_client_uri", registrationUri);
}
// add in all other client properties
// OAuth DynReg
o.add("redirect_uris", getAsArray(c.getRedirectUris()));
o.addProperty("client_name", c.getClientName());
@ -168,7 +168,7 @@ public class ClientDetailsEntityJsonProcessor {
o.add("grant_types", getAsArray(c.getGrantTypes()));
o.addProperty("policy_uri", c.getPolicyUri());
o.addProperty("jwks_uri", c.getJwksUri());
// OIDC Registration
o.addProperty("application_type", c.getApplicationType() != null ? c.getApplicationType().getValue() : null);
o.addProperty("sector_identifier_uri", c.getSectorIdentifierUri());
@ -186,7 +186,7 @@ public class ClientDetailsEntityJsonProcessor {
o.addProperty("initiate_login_uri", c.getInitiateLoginUri());
o.addProperty("post_logout_redirect_uri", c.getPostLogoutRedirectUri());
o.add("request_uris", getAsArray(c.getRequestUris()));
return o;
return o;
}
/**

View File

@ -20,7 +20,7 @@ package org.mitre.openid.connect.config;
/**
* Bean to hold configuration information that must be injected into various parts
* of our application. Set all of the properties here, and autowire a reference
* to this bean if you need access to any configuration properties.
* to this bean if you need access to any configuration properties.
*
* @author AANGANES
*
@ -28,22 +28,22 @@ package org.mitre.openid.connect.config;
public class ConfigurationPropertiesBean {
private String issuer;
private String topbarTitle;
private String logoImageUrl;
public ConfigurationPropertiesBean() {
}
/**
* @return the issuer baseUrl
*/
public String getIssuer() {
return issuer;
}
/**
* @param iss the issuer to set
*/

View File

@ -29,13 +29,13 @@ public class ServerConfiguration {
private String authorizationEndpointUri;
private String tokenEndpointUri;
private String registrationEndpointUri;
private String issuer;
private String jwksUri;
private String userInfoUri;
/**
@ -125,78 +125,78 @@ public class ServerConfiguration {
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((authorizationEndpointUri == null) ? 0 : authorizationEndpointUri.hashCode());
result = prime * result + ((issuer == null) ? 0 : issuer.hashCode());
result = prime * result + ((jwksUri == null) ? 0 : jwksUri.hashCode());
result = prime * result + ((registrationEndpointUri == null) ? 0 : registrationEndpointUri.hashCode());
result = prime * result + ((tokenEndpointUri == null) ? 0 : tokenEndpointUri.hashCode());
result = prime * result + ((userInfoUri == null) ? 0 : userInfoUri.hashCode());
return result;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((authorizationEndpointUri == null) ? 0 : authorizationEndpointUri.hashCode());
result = prime * result + ((issuer == null) ? 0 : issuer.hashCode());
result = prime * result + ((jwksUri == null) ? 0 : jwksUri.hashCode());
result = prime * result + ((registrationEndpointUri == null) ? 0 : registrationEndpointUri.hashCode());
result = prime * result + ((tokenEndpointUri == null) ? 0 : tokenEndpointUri.hashCode());
result = prime * result + ((userInfoUri == null) ? 0 : userInfoUri.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ServerConfiguration other = (ServerConfiguration) obj;
if (authorizationEndpointUri == null) {
if (other.authorizationEndpointUri != null) {
return false;
}
} else if (!authorizationEndpointUri.equals(other.authorizationEndpointUri)) {
return false;
}
if (issuer == null) {
if (other.issuer != null) {
return false;
}
} else if (!issuer.equals(other.issuer)) {
return false;
}
if (jwksUri == null) {
if (other.jwksUri != null) {
return false;
}
} else if (!jwksUri.equals(other.jwksUri)) {
return false;
}
if (registrationEndpointUri == null) {
if (other.registrationEndpointUri != null) {
return false;
}
} else if (!registrationEndpointUri.equals(other.registrationEndpointUri)) {
return false;
}
if (tokenEndpointUri == null) {
if (other.tokenEndpointUri != null) {
return false;
}
} else if (!tokenEndpointUri.equals(other.tokenEndpointUri)) {
return false;
}
if (userInfoUri == null) {
if (other.userInfoUri != null) {
return false;
}
} else if (!userInfoUri.equals(other.userInfoUri)) {
return false;
}
return true;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ServerConfiguration other = (ServerConfiguration) obj;
if (authorizationEndpointUri == null) {
if (other.authorizationEndpointUri != null) {
return false;
}
} else if (!authorizationEndpointUri.equals(other.authorizationEndpointUri)) {
return false;
}
if (issuer == null) {
if (other.issuer != null) {
return false;
}
} else if (!issuer.equals(other.issuer)) {
return false;
}
if (jwksUri == null) {
if (other.jwksUri != null) {
return false;
}
} else if (!jwksUri.equals(other.jwksUri)) {
return false;
}
if (registrationEndpointUri == null) {
if (other.registrationEndpointUri != null) {
return false;
}
} else if (!registrationEndpointUri.equals(other.registrationEndpointUri)) {
return false;
}
if (tokenEndpointUri == null) {
if (other.tokenEndpointUri != null) {
return false;
}
} else if (!tokenEndpointUri.equals(other.tokenEndpointUri)) {
return false;
}
if (userInfoUri == null) {
if (other.userInfoUri != null) {
return false;
}
} else if (!userInfoUri.equals(other.userInfoUri)) {
return false;
}
return true;
}
}

View File

@ -27,7 +27,7 @@ import javax.persistence.Table;
@Table(name="address")
public class Address {
private Long id;
private String formatted;
private String streetAddress;
@ -35,14 +35,14 @@ public class Address {
private String region;
private String postalCode;
private String country;
/**
* Empty constructor
*/
public Address() {
}
/**
* @return the formatted address string
*/
@ -125,19 +125,19 @@ public class Address {
}
/**
* @return the id
*/
* @return the id
*/
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
public Long getId() {
return id;
}
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
}

View File

@ -45,164 +45,164 @@ import javax.persistence.Transient;
})
public class ApprovedSite {
// unique id
private Long id;
// which user made the approval
// unique id
private Long id;
// which user made the approval
private String userId;
// which OAuth2 client is this tied to
private String clientId;
// when was this first approved?
private Date creationDate;
// when was this last accessed?
private Date accessDate;
// if this is a time-limited access, when does it run out?
private Date timeoutDate;
// what scopes have been allowed
// this should include all information for what data to access
private Set<String> allowedScopes;
// If this AP is a WS, link to the WS
private WhitelistedSite whitelistedSite;
// TODO: should we store the OAuth2 tokens and IdTokens here?
/**
* Empty constructor
*/
public ApprovedSite() {
}
}
/**
* @return the id
*/
* @return the id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the userInfo
*/
@Basic
@Column(name="user_id")
public String getUserId() {
return userId;
}
* @return the userInfo
*/
@Basic
@Column(name="user_id")
public String getUserId() {
return userId;
}
/**
* @param userInfo the userInfo to set
*/
public void setUserId(String userId) {
this.userId = userId;
}
* @param userInfo the userInfo to set
*/
public void setUserId(String userId) {
this.userId = userId;
}
/**
* @return the clientId
*/
@Basic
@Column(name="client_id")
public String getClientId() {
return clientId;
}
* @return the clientId
*/
@Basic
@Column(name="client_id")
public String getClientId() {
return clientId;
}
/**
* @param clientId the clientId to set
*/
public void setClientId(String clientId) {
this.clientId = clientId;
}
* @param clientId the clientId to set
*/
public void setClientId(String clientId) {
this.clientId = clientId;
}
/**
* @return the creationDate
*/
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Column(name="creation_date")
public Date getCreationDate() {
return creationDate;
}
* @return the creationDate
*/
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Column(name="creation_date")
public Date getCreationDate() {
return creationDate;
}
/**
* @param creationDate the creationDate to set
*/
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
* @param creationDate the creationDate to set
*/
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
/**
* @return the accessDate
*/
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Column(name="access_date")
public Date getAccessDate() {
return accessDate;
}
* @return the accessDate
*/
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Column(name="access_date")
public Date getAccessDate() {
return accessDate;
}
/**
* @param accessDate the accessDate to set
*/
public void setAccessDate(Date accessDate) {
this.accessDate = accessDate;
}
* @param accessDate the accessDate to set
*/
public void setAccessDate(Date accessDate) {
this.accessDate = accessDate;
}
/**
* @return the allowedScopes
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="approved_site_scope",
joinColumns=@JoinColumn(name="owner_id")
)
@Column(name="scope")
public Set<String> getAllowedScopes() {
return allowedScopes;
}
* @return the allowedScopes
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="approved_site_scope",
joinColumns=@JoinColumn(name="owner_id")
)
@Column(name="scope")
public Set<String> getAllowedScopes() {
return allowedScopes;
}
/**
* @param allowedScopes the allowedScopes to set
*/
public void setAllowedScopes(Set<String> allowedScopes) {
this.allowedScopes = allowedScopes;
}
* @param allowedScopes the allowedScopes to set
*/
public void setAllowedScopes(Set<String> allowedScopes) {
this.allowedScopes = allowedScopes;
}
/**
* @return the timeoutDate
*/
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Column(name="timeout_date")
public Date getTimeoutDate() {
return timeoutDate;
}
* @return the timeoutDate
*/
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Column(name="timeout_date")
public Date getTimeoutDate() {
return timeoutDate;
}
/**
* @param timeoutDate the timeoutDate to set
*/
public void setTimeoutDate(Date timeoutDate) {
this.timeoutDate = timeoutDate;
}
* @param timeoutDate the timeoutDate to set
*/
public void setTimeoutDate(Date timeoutDate) {
this.timeoutDate = timeoutDate;
}
/**
* Does this AP entry correspond to a WS?
* @return
*/
@Transient
/**
* Does this AP entry correspond to a WS?
* @return
*/
@Transient
public Boolean getIsWhitelisted() {
return (whitelistedSite != null);
}
@ -220,10 +220,10 @@ public class ApprovedSite {
/**
* Has this approval expired?
* @return
*/
* @return
*/
@Transient
public boolean isExpired() {
public boolean isExpired() {
if (getTimeoutDate() != null) {
Date now = new Date();
if (now.after(getTimeoutDate())) {
@ -234,6 +234,6 @@ public class ApprovedSite {
} else {
return false;
}
}
}
}

View File

@ -24,41 +24,41 @@ import javax.persistence.Table;
})
public class BlacklistedSite {
// unique id
private Long id;
// URI pattern to black list
private String uri;
public BlacklistedSite() {
}
// unique id
private Long id;
// URI pattern to black list
private String uri;
public BlacklistedSite() {
}
/**
* @return the id
*/
* @return the id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
@Basic
@Column(name="uri")
public String getUri() {
return uri;
}
@Basic
@Column(name="uri")
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public void setUri(String uri) {
this.uri = uri;
}
}

View File

@ -33,21 +33,21 @@ import com.google.gson.JsonObject;
@Table(name="user_info")
@NamedQueries({
@NamedQuery(name="DefaultUserInfo.getAll", query = "select u from DefaultUserInfo u"),
@NamedQuery(name="DefaultUserInfo.getByUsername", query = "select u from DefaultUserInfo u WHERE u.preferredUsername = :username"),
@NamedQuery(name="DefaultUserInfo.getBySubject", query = "select u from DefaultUserInfo u WHERE u.sub = :sub")
@NamedQuery(name="DefaultUserInfo.getByUsername", query = "select u from DefaultUserInfo u WHERE u.preferredUsername = :username"),
@NamedQuery(name="DefaultUserInfo.getBySubject", query = "select u from DefaultUserInfo u WHERE u.sub = :sub")
})
public class DefaultUserInfo implements UserInfo {
private Long id;
private String sub;
private String sub;
private String preferredUsername;
private String name;
private String givenName;
private String familyName;
private String middleName;
private String nickname;
private String name;
private String givenName;
private String familyName;
private String middleName;
private String nickname;
private String profile;
private String picture;
private String picture;
private String website;
private String email;
private Boolean emailVerified;
@ -58,8 +58,8 @@ public class DefaultUserInfo implements UserInfo {
private Address address;
private String updatedTime;
private String birthdate;
/**
* @return the id
*/
@ -356,21 +356,23 @@ public class DefaultUserInfo implements UserInfo {
}
/**
* @return the birthdate
*/
* @return the birthdate
*/
@Override
@Basic
@Column(name="birthdate")
public String getBirthdate() {
return birthdate;
}
public String getBirthdate() {
return birthdate;
}
/**
* @param birthdate the birthdate to set
*/
public void setBirthdate(String birthdate) {
this.birthdate = birthdate;
}
* @param birthdate the birthdate to set
*/
@Override
public void setBirthdate(String birthdate) {
this.birthdate = birthdate;
}
/**
/**
* Parse a JsonObject into a UserInfo.
* @param o
* @return
@ -379,7 +381,7 @@ public class DefaultUserInfo implements UserInfo {
DefaultUserInfo ui = new DefaultUserInfo();
ui.setSub(obj.has("sub") ? obj.get("sub").getAsString() : null);
ui.setName(obj.has("name") ? obj.get("name").getAsString() : null);
ui.setPreferredUsername(obj.has("preferred_username") ? obj.get("preferred_username").getAsString() : null);
ui.setGivenName(obj.has("given_name") ? obj.get("given_name").getAsString() : null);
@ -394,29 +396,29 @@ public class DefaultUserInfo implements UserInfo {
ui.setLocale(obj.has("locale") ? obj.get("locale").getAsString() : null);
ui.setUpdatedTime(obj.has("updated_time") ? obj.get("updated_time").getAsString() : null);
ui.setBirthdate(obj.has("birthdate") ? obj.get("birthdate").getAsString() : null);
ui.setEmail(obj.has("email") ? obj.get("email").getAsString() : null);
ui.setEmailVerified(obj.has("email_verified") ? obj.get("email_verified").getAsBoolean() : null);
ui.setPhoneNumber(obj.has("phone_number") ? obj.get("phone_number").getAsString() : null);
if (obj.has("address") && obj.get("address").isJsonObject()) {
JsonObject addr = obj.get("address").getAsJsonObject();
ui.setAddress(new Address());
ui.getAddress().setFormatted(addr.has("formatted") ? addr.get("formatted").getAsString() : null);
ui.getAddress().setStreetAddress(addr.has("street_address") ? addr.get("street_address").getAsString() : null);
ui.getAddress().setLocality(addr.has("locality") ? addr.get("locality").getAsString() : null);
ui.getAddress().setRegion(addr.has("region") ? addr.get("region").getAsString() : null);
ui.getAddress().setPostalCode(addr.has("postal_code") ? addr.get("postal_code").getAsString() : null);
ui.getAddress().setCountry(addr.has("country") ? addr.get("country").getAsString() : null);
}
return ui;
}
}

View File

@ -37,50 +37,50 @@ import javax.persistence.Temporal;
public class Event {
public static enum EventType { LOGIN, AUTHORIZATION, ACCESS }
private Long id;
private EventType type;
private Date timestamp;
/**
* @return the id
*/
* @return the id
*/
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
public Long getId() {
return id;
}
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the type
*/
public EventType getType() {
return type;
}
* @return the type
*/
public EventType getType() {
return type;
}
/**
* @param type the type to set
*/
public void setType(EventType type) {
this.type = type;
}
* @param type the type to set
*/
public void setType(EventType type) {
this.type = type;
}
/**
* @return the timestamp
*/
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
public Date getTimestamp() {
return timestamp;
}
* @return the timestamp
*/
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
public Date getTimestamp() {
return timestamp;
}
/**
* @param timestamp the timestamp to set
*/
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
* @param timestamp the timestamp to set
*/
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
}

View File

@ -23,16 +23,16 @@ import javax.persistence.Temporal;
})
public class Nonce {
private Long id; //the ID of this Nonce
private String value; //the value of this Nonce
private String clientId;//The id of the client who used this Nonce
private Date useDate; //the date this Nonce was used
private Date expireDate; //the date after which this Nonce should be removed from the database
private Date expireDate; //the date after which this Nonce should be removed from the database
/**
* @return the id
@ -86,7 +86,7 @@ public class Nonce {
* @return the useDate
*/
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Column(name="use_date")
public Date getUseDate() {
return useDate;
@ -103,7 +103,7 @@ public class Nonce {
* @return the expireDate
*/
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Column(name="expire_date")
public Date getExpireDate() {
return expireDate;
@ -115,8 +115,8 @@ public class Nonce {
public void setExpireDate(Date expireDate) {
this.expireDate = expireDate;
}
}

View File

@ -12,12 +12,12 @@ public interface UserInfo {
* @param sub the userId to set
*/
public abstract void setSub(String sub);
/**
* @return the preferred username
*/
public abstract String getPreferredUsername();
/**
* @param preferredUsername the preferredUsername to set
*/
@ -189,7 +189,7 @@ public interface UserInfo {
* @return
*/
public abstract String getBirthdate();
/**
*
* @param birthdate

View File

@ -32,7 +32,7 @@ import javax.persistence.NamedQuery;
import javax.persistence.Table;
/**
* Indicator that login to a site should be automatically granted
* Indicator that login to a site should be automatically granted
* without user interaction.
* @author jricher, aanganes
*
@ -40,21 +40,21 @@ import javax.persistence.Table;
@Entity
@Table(name="whitelisted_site")
@NamedQueries({
@NamedQuery(name = "WhitelistedSite.getAll", query = "select w from WhitelistedSite w"),
@NamedQuery(name = "WhitelistedSite.getAll", query = "select w from WhitelistedSite w"),
@NamedQuery(name = "WhitelistedSite.getByClientId", query = "select w from WhitelistedSite w where w.clientId = :clientId"),
@NamedQuery(name = "WhitelistedSite.getByCreatoruserId", query = "select w from WhitelistedSite w where w.creatorUserId = :userId")
})
public class WhitelistedSite {
// unique id
private Long id;
// Reference to the admin user who created this entry
// unique id
private Long id;
// Reference to the admin user who created this entry
private String creatorUserId;
// which OAuth2 client is this tied to
private String clientId;
// what scopes be allowed by default
// this should include all information for what data to access
private Set<String> allowedScopes;
@ -63,14 +63,14 @@ public class WhitelistedSite {
* Empty constructor
*/
public WhitelistedSite() {
}
/**
* @return the id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
@ -103,9 +103,9 @@ public class WhitelistedSite {
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="whitelisted_site_scope",
joinColumns=@JoinColumn(name="owner_id")
)
name="whitelisted_site_scope",
joinColumns=@JoinColumn(name="owner_id")
)
@Column(name="scope")
public Set<String> getAllowedScopes() {
return allowedScopes;

View File

@ -50,7 +50,7 @@ public interface ApprovedSiteRepository {
* @param clientId
* @param userId
* @return
*/
*/
public Collection<ApprovedSite> getByClientIdAndUserId(String clientId, String userId);
/**
@ -69,14 +69,14 @@ public interface ApprovedSiteRepository {
* @return the persisted entity
*/
public ApprovedSite save(ApprovedSite approvedSite);
/**
* Get all sites approved by this user
* @param userId
* @return
*/
public Collection<ApprovedSite> getByUserId(String userId);
/**
* Get all sites associated with this client
* @param clientId

View File

@ -14,13 +14,13 @@ import org.mitre.openid.connect.model.BlacklistedSite;
public interface BlacklistedSiteRepository {
public Collection<BlacklistedSite> getAll();
public BlacklistedSite getById(Long id);
public void remove(BlacklistedSite blacklistedSite);
public BlacklistedSite save(BlacklistedSite blacklistedSite);
public BlacklistedSite update(BlacklistedSite oldBlacklistedSite, BlacklistedSite blacklistedSite);
}

View File

@ -47,8 +47,8 @@ public interface EventRepository {
* @param startChunk
* the start chuck of a list you desire
* @param chunkSize
* the size of the chunk you desire
*
* the size of the chunk you desire
*
* @return a Collection of Events
*/
public Collection<Event> getEventsDuringPeriod(Date start, Date end, int startChunk, int chunkSize);

View File

@ -1,6 +1,7 @@
package org.mitre.openid.connect.repository;
import java.util.Collection;
import org.mitre.openid.connect.model.Nonce;
/**
@ -19,14 +20,14 @@ public interface NonceRepository {
* @return the nonce, if found
*/
public Nonce getById(Long id);
/**
* Remove the given Nonce from the database
*
* @param nonce the Nonce to remove
*/
public void remove(Nonce nonce);
/**
* Save a new Nonce in the database
*
@ -34,21 +35,21 @@ public interface NonceRepository {
* @return the saved Nonce
*/
public Nonce save(Nonce nonce);
/**
* Return all nonces stored in the database
*
* @return the set of nonces
*/
public Collection<Nonce> getAll();
/**
* Return all expired nonces stored in the database
*
* @return the set of expired nonces
*/
public Collection<Nonce> getExpired();
/**
* Return the set of nonces registered to the given client ID
*
@ -56,5 +57,5 @@ public interface NonceRepository {
* @return the set of nonces registered to the client
*/
public Collection<Nonce> getByClientId(String clientId);
}

View File

@ -26,24 +26,24 @@ import org.mitre.openid.connect.model.UserInfo;
*
*/
public interface UserInfoRepository {
/**
* Returns the UserInfo for the given subject
*
* @param sub
* the subject of the UserInfo
* @return a valid UserInfo if it exists, null otherwise
*/
public UserInfo getBySubject(String sub);
*/
public UserInfo getBySubject(String sub);
/**
* Persists a UserInfo
* Persists a UserInfo
*
* @param user
* @return
*/
public UserInfo save(UserInfo userInfo);
/**
* Removes the given UserInfo from the repository
*
@ -64,6 +64,6 @@ public interface UserInfoRepository {
* @param username
* @return
*/
public UserInfo getByUsername(String username);
public UserInfo getByUsername(String username);
}

View File

@ -42,7 +42,7 @@ public interface WhitelistedSiteRepository {
* @return a valid WhitelistedSite if it exists, null otherwise
*/
public WhitelistedSite getById(Long id);
/**
* Find a WhitelistedSite by its associated ClientDetails reference
*
@ -50,7 +50,7 @@ public interface WhitelistedSiteRepository {
* @return the corresponding WhitelistedSite if one exists for the RP, or null
*/
public WhitelistedSite getByClientId(String clientId);
/**
* Return a collection of the WhitelistedSites created by a given user
*
@ -77,10 +77,10 @@ public interface WhitelistedSiteRepository {
/**
* Persist changes to a whitelistedSite. The ID of oldWhitelistedSite is retained.
* @param oldWhitelistedSite
* @param whitelistedSite
* @return
*/
public WhitelistedSite update(WhitelistedSite oldWhitelistedSite, WhitelistedSite whitelistedSite);
* @param oldWhitelistedSite
* @param whitelistedSite
* @return
*/
public WhitelistedSite update(WhitelistedSite oldWhitelistedSite, WhitelistedSite whitelistedSite);
}

View File

@ -30,17 +30,17 @@ import org.springframework.security.oauth2.provider.ClientDetails;
*
*/
public interface ApprovedSiteService {
public ApprovedSite createApprovedSite(String clientId, String userId, Date timeoutDate, Set<String> allowedScopes, WhitelistedSite whitelistedSite);
/**
* Return a collection of all ApprovedSites
*
* @return the ApprovedSite collection, or null
*/
public Collection<ApprovedSite> getAll();
/**
* Return a collection of ApprovedSite managed by this repository matching the
* provided client ID and user ID
@ -48,9 +48,9 @@ public interface ApprovedSiteService {
* @param clientId
* @param userId
* @return
*/
*/
public Collection<ApprovedSite> getByClientIdAndUserId(String clientId, String userId);
/**
* Save an ApprovedSite
*
@ -82,14 +82,14 @@ public interface ApprovedSiteService {
* @return
*/
public Collection<ApprovedSite> getByUserId(String userId);
/**
* Get all sites associated with this client
* @param clientId
* @return
*/
public Collection<ApprovedSite> getByClientId(String clientId);
/**
* Clear out any approved sites for a given client.
* @param client

View File

@ -14,15 +14,15 @@ import org.mitre.openid.connect.model.BlacklistedSite;
public interface BlacklistedSiteService {
public Collection<BlacklistedSite> getAll();
public BlacklistedSite getById(Long id);
public void remove(BlacklistedSite blacklistedSite);
public BlacklistedSite saveNew(BlacklistedSite blacklistedSite);
public BlacklistedSite update(BlacklistedSite oldBlacklistedSite, BlacklistedSite blacklistedSite);
public boolean isBlacklisted(String uri);
}

View File

@ -15,24 +15,24 @@ import org.mitre.openid.connect.model.Nonce;
public interface NonceService {
/**
* Create a new nonce.
*
* Create a new nonce.
*
* @param clientId the ID of the client
* @param value the value of the Nonce
* @return the saved Nonce
*/
public Nonce create(String clientId, String value);
/**
* Check whether a given nonce value has been previously used and stored
* by the client.
* by the client.
*
* @param clientId the ID of the client
* @param value the value of the nonce
* @return true if the nonce has already been used, false otherwise
*/
public boolean alreadyUsed(String clientId, String value);
public boolean alreadyUsed(String clientId, String value);
/**
* Return the nonce with the given ID
*
@ -40,14 +40,14 @@ public interface NonceService {
* @return the nonce, if found
*/
public Nonce getById(Long id);
/**
* Remove the given Nonce from the database
*
* @param nonce the Nonce to remove
*/
public void remove(Nonce nonce);
/**
* Save a new Nonce in the database
*
@ -55,21 +55,21 @@ public interface NonceService {
* @return the saved Nonce
*/
public Nonce save(Nonce nonce);
/**
* Return all nonces stored in the database
*
* @return the set of nonces
*/
public Collection<Nonce> getAll();
/**
* Return all expired nonces stored in the database
*
* @return the set of expired nonces
*/
public Collection<Nonce> getExpired();
/**
* Return the set of nonces registered to the given client ID
*
@ -82,5 +82,5 @@ public interface NonceService {
* Clear expired nonces from the database
*/
void clearExpiredNonces();
}

View File

@ -14,9 +14,9 @@ public interface StatsService {
/**
* Calculate summary statistics
* approvalCount: total approved sites
* userCount: unique users
* clientCount: unique clients
*
* userCount: unique users
* clientCount: unique clients
*
* @return
*/
public Map<String, Integer> calculateSummaryStats();

View File

@ -41,7 +41,7 @@ public interface UserInfoService {
* @return UserInfo for sub, or null
*/
public UserInfo getBySubject(String userId);
/**
* Remove the UserInfo
*

View File

@ -33,7 +33,7 @@ public interface WhitelistedSiteService {
* @return the WhitelistedSite collection, or null
*/
public Collection<WhitelistedSite> getAll();
/**
* Returns the WhitelistedSite for the given id
*
@ -50,7 +50,7 @@ public interface WhitelistedSiteService {
* @return the corresponding WhitelistedSite if one exists for the RP, or null
*/
public WhitelistedSite getByClientId(String clientId);
/**
* Return a collection of the WhitelistedSites created by a given user
*
@ -58,7 +58,7 @@ public interface WhitelistedSiteService {
* @return the collection of corresponding WhitelistedSites, if any, or null
*/
public Collection<WhitelistedSite> getByCreator(String creatorId);
/**
* Removes the given WhitelistedSite from the repository
*
@ -75,10 +75,10 @@ public interface WhitelistedSiteService {
* @return
*/
public WhitelistedSite saveNew(WhitelistedSite whitelistedSite);
/**
* Updates an existing whitelisted site
*/
public WhitelistedSite update(WhitelistedSite oldWhitelistedSite, WhitelistedSite whitelistedSite);
}

View File

@ -42,27 +42,27 @@ import com.nimbusds.jose.jwk.JWKSet;
public class JwkKeyListView extends AbstractView {
private static Logger logger = LoggerFactory.getLogger(JwkKeyListView.class);
@Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) {
response.setContentType("application/json");
//BiMap<String, PublicKey> keyMap = (BiMap<String, PublicKey>) model.get("keys");
Map<String, JWK> keys = (Map<String, JWK>) model.get("keys");
JWKSet jwkSet = new JWKSet(new ArrayList<JWK>(keys.values()));
try {
Writer out = response.getWriter();
out.write(jwkSet.toString());
} catch (IOException e) {
logger.error("IOException in JwkKeyListView.java: ", e);
}
}

View File

@ -27,26 +27,26 @@ import org.springframework.dao.IncorrectResultSizeDataAccessException;
* Time: 2:13 PM
*/
public class JpaUtil {
public static <T> T getSingleResult(List<T> list) {
switch(list.size()) {
case 0:
return null;
case 1:
return list.get(0);
default:
throw new IncorrectResultSizeDataAccessException(1);
}
}
public static <T> T getSingleResult(List<T> list) {
switch(list.size()) {
case 0:
return null;
case 1:
return list.get(0);
default:
throw new IncorrectResultSizeDataAccessException(1);
}
}
public static <T, I> T saveOrUpdate(I id, EntityManager entityManager, T entity) {
if (id == null) {
entityManager.persist(entity);
entityManager.flush();
return entity;
} else {
T tmp = entityManager.merge(entity);
entityManager.flush();
return tmp;
}
}
public static <T, I> T saveOrUpdate(I id, EntityManager entityManager, T entity) {
if (id == null) {
entityManager.persist(entity);
entityManager.flush();
return entity;
} else {
T tmp = entityManager.merge(entity);
entityManager.flush();
return tmp;
}
}
}

View File

@ -10,7 +10,6 @@ import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.mitre.openid.connect.view.JsonEntityView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
@ -35,63 +34,66 @@ public class WebfingerView extends AbstractView {
private static Logger logger = LoggerFactory.getLogger(WebfingerView.class);
private Gson gson = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
public boolean shouldSkipField(FieldAttributes f) {
return false;
}
public boolean shouldSkipClass(Class<?> clazz) {
// skip the JPA binding wrapper
if (clazz.equals(BeanPropertyBindingResult.class)) {
return true;
}
return false;
}
})
.serializeNulls()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.create();
.setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return false;
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
// skip the JPA binding wrapper
if (clazz.equals(BeanPropertyBindingResult.class)) {
return true;
}
return false;
}
})
.serializeNulls()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.create();
@Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) {
response.setContentType("application/jrd+json");
HttpStatus code = (HttpStatus) model.get("code");
if (code == null) {
code = HttpStatus.OK; // default to 200
}
response.setStatus(code.value());
try {
String resource = (String)model.get("resource");
String issuer = (String)model.get("issuer");
JsonObject obj = new JsonObject();
obj.addProperty("subject", resource);
JsonArray links = new JsonArray();
JsonObject link = new JsonObject();
link.addProperty("rel", "http://openid.net/specs/connect/1.0/issuer");
link.addProperty("href", issuer);
links.add(link);
obj.add("links", links);
Writer out = response.getWriter();
gson.toJson(obj, out);
gson.toJson(obj, out);
} catch (IOException e) {
//TODO: Error Handling
logger.error("IOException in JsonEntityView.java: ", e);
}
}
}
}

View File

@ -17,7 +17,6 @@ package org.mitre.discovery.web;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -53,20 +52,20 @@ import com.nimbusds.jose.Algorithm;
public class DiscoveryEndpoint {
private static Logger logger = LoggerFactory.getLogger(DiscoveryEndpoint.class);
@Autowired
private ConfigurationPropertiesBean config;
private ConfigurationPropertiesBean config;
@Autowired
private SystemScopeService scopeService;
@Autowired
private JwtSigningAndValidationService jwtService;
@Autowired
private UserInfoService userService;
// used to map JWA algorithms objects to strings
private Function<Algorithm, String> toAlgorithmName = new Function<Algorithm, String>() {
@Override
@ -78,7 +77,7 @@ public class DiscoveryEndpoint {
}
}
};
@RequestMapping(value={"/.well-known/webfinger"},
params={"resource", "rel=http://openid.net/specs/connect/1.0/issuer"}, produces = "application/json")
public String webfinger(@RequestParam("resource") String resource, Model model) {
@ -89,10 +88,10 @@ public class DiscoveryEndpoint {
try {
URI resourceUri = new URI(resource);
if (resourceUri != null
&& resourceUri.getScheme() != null
&& resourceUri.getScheme() != null
&& resourceUri.getScheme().equals("acct")) {
// acct: URI
// split out the user and host parts
List<String> parts = Lists.newArrayList(Splitter.on("@").split(resourceUri.getSchemeSpecificPart()));
@ -100,14 +99,14 @@ public class DiscoveryEndpoint {
if (parts.size() > 0) {
user = userService.getByUsername(parts.get(0)); // first part is the username
}
if (user == null) {
logger.info("User not found: " + resource);
model.addAttribute("code", HttpStatus.NOT_FOUND);
return "httpCodeView";
}
// TODO: check the "host" part against our issuer
// TODO: check the "host" part against our issuer
} else {
logger.info("Unknown URI format: " + resource);
model.addAttribute("code", HttpStatus.NOT_FOUND);
@ -119,96 +118,96 @@ public class DiscoveryEndpoint {
return "httpCodeView";
}
}
// if we got here, then we're good
model.addAttribute("resource", resource);
model.addAttribute("issuer", config.getIssuer());
return "webfingerView";
}
@RequestMapping("/.well-known/openid-configuration")
public String providerConfiguration(Model model) {
/*
/*
*
version
REQUIRED. Version string of the provider response. "3.0" is the expected value.
REQUIRED. Version string of the provider response. "3.0" is the expected value.
issuer
REQUIRED. URL using the https scheme with no query or fragment component that the OP asserts as its Issuer Identifier.
REQUIRED. URL using the https scheme with no query or fragment component that the OP asserts as its Issuer Identifier.
authorization_endpoint
OPTIONAL. URL of the OP's Authentication and Authorization Endpoint [OpenID.Messages].
OPTIONAL. URL of the OP's Authentication and Authorization Endpoint [OpenID.Messages].
token_endpoint
OPTIONAL. URL of the OP's OAuth 2.0 Token Endpoint [OpenID.Messages].
OPTIONAL. URL of the OP's OAuth 2.0 Token Endpoint [OpenID.Messages].
userinfo_endpoint
RECOMMENDED. URL of the OP's UserInfo Endpoint [OpenID.Messages]. This URL MUST use the https scheme and MAY contain port, path, and query parameter components.
RECOMMENDED. URL of the OP's UserInfo Endpoint [OpenID.Messages]. This URL MUST use the https scheme and MAY contain port, path, and query parameter components.
check_session_iframe
OPTIONAL. URL of an OP endpoint that provides a page to support cross-origin communications for session state information with the RP Client, using the HTML5 postMessage API. The page is loaded from an invisible iframe embedded in an RP page so that it can run in the OP's security context.[OpenID.Session]
OPTIONAL. URL of an OP endpoint that provides a page to support cross-origin communications for session state information with the RP Client, using the HTML5 postMessage API. The page is loaded from an invisible iframe embedded in an RP page so that it can run in the OP's security context.[OpenID.Session]
end_session_endpoint
OPTIONAL. URL of the OP's endpoint that initiates the user logout [OpenID.Session].
OPTIONAL. URL of the OP's endpoint that initiates the user logout [OpenID.Session].
jwks_uri
OPTIONAL. URL of the OP's JSON Web Key Set [JWK] document that contains the Server's signing key(s) that are used for signing responses to the Client. The JWK Set MAY also contain the Server's encryption key(s) that are used by the Client to encrypt requests to the Server. When both signing and encryption keys are made available, a use (Key Use) parameter value is REQUIRED for all keys in the document to indicate each key's intended usage.
OPTIONAL. URL of the OP's JSON Web Key Set [JWK] document that contains the Server's signing key(s) that are used for signing responses to the Client. The JWK Set MAY also contain the Server's encryption key(s) that are used by the Client to encrypt requests to the Server. When both signing and encryption keys are made available, a use (Key Use) parameter value is REQUIRED for all keys in the document to indicate each key's intended usage.
registration_endpoint
RECOMMENDED. URL of the OP's Dynamic Client Registration Endpoint [OpenID.Registration].
RECOMMENDED. URL of the OP's Dynamic Client Registration Endpoint [OpenID.Registration].
scopes_supported
RECOMMENDED. JSON array containing a list of the OAuth 2.0 [RFC6749] scope values that this server supports. The server MUST support the openid scope value.
RECOMMENDED. JSON array containing a list of the OAuth 2.0 [RFC6749] scope values that this server supports. The server MUST support the openid scope value.
response_types_supported
REQUIRED. JSON array containing a list of the OAuth 2.0 response_type values that this server supports. The server MUST support the code, id_token, and the token id_token response type values.
REQUIRED. JSON array containing a list of the OAuth 2.0 response_type values that this server supports. The server MUST support the code, id_token, and the token id_token response type values.
grant_types_supported
OPTIONAL. JSON array containing a list of the OAuth 2.0 grant type values that this server supports. The server MUST support the authorization_code and implicit grant type values and MAY support the urn:ietf:params:oauth:grant-type:jwt-bearer grant type defined in OAuth JWT Bearer Token Profiles [OAuth.JWT]. If omitted, the default value is ["authorization_code", "implicit"].
OPTIONAL. JSON array containing a list of the OAuth 2.0 grant type values that this server supports. The server MUST support the authorization_code and implicit grant type values and MAY support the urn:ietf:params:oauth:grant-type:jwt-bearer grant type defined in OAuth JWT Bearer Token Profiles [OAuth.JWT]. If omitted, the default value is ["authorization_code", "implicit"].
acr_values_supported
OPTIONAL. JSON array containing a list of the Authentication Context Class References that this server supports.
OPTIONAL. JSON array containing a list of the Authentication Context Class References that this server supports.
subject_types_supported
REQUIRED. JSON array containing a list of the subject identifier types that this server supports. Valid types include pairwise and public.
REQUIRED. JSON array containing a list of the subject identifier types that this server supports. Valid types include pairwise and public.
userinfo_signing_alg_values_supported
OPTIONAL. JSON array containing a list of the JWS [JWS] signing algorithms (alg values) [JWA] supported by the UserInfo Endpoint to encode the Claims in a JWT [JWT].
OPTIONAL. JSON array containing a list of the JWS [JWS] signing algorithms (alg values) [JWA] supported by the UserInfo Endpoint to encode the Claims in a JWT [JWT].
userinfo_encryption_alg_values_supported
OPTIONAL. JSON array containing a list of the JWE [JWE] encryption algorithms (alg values) [JWA] supported by the UserInfo Endpoint to encode the Claims in a JWT [JWT].
OPTIONAL. JSON array containing a list of the JWE [JWE] encryption algorithms (alg values) [JWA] supported by the UserInfo Endpoint to encode the Claims in a JWT [JWT].
userinfo_encryption_enc_values_supported
OPTIONAL. JSON array containing a list of the JWE encryption algorithms (enc values) [JWA] supported by the UserInfo Endpoint to encode the Claims in a JWT [JWT].
OPTIONAL. JSON array containing a list of the JWE encryption algorithms (enc values) [JWA] supported by the UserInfo Endpoint to encode the Claims in a JWT [JWT].
id_token_signing_alg_values_supported
REQUIRED. JSON array containing a list of the JWS signing algorithms (alg values) supported by the Authorization Server for the ID Token to encode the Claims in a JWT [JWT].
REQUIRED. JSON array containing a list of the JWS signing algorithms (alg values) supported by the Authorization Server for the ID Token to encode the Claims in a JWT [JWT].
id_token_encryption_alg_values_supported
OPTIONAL. JSON array containing a list of the JWE encryption algorithms (alg values) supported by the Authorization Server for the ID Token to encode the Claims in a JWT [JWT].
OPTIONAL. JSON array containing a list of the JWE encryption algorithms (alg values) supported by the Authorization Server for the ID Token to encode the Claims in a JWT [JWT].
id_token_encryption_enc_values_supported
OPTIONAL. JSON array containing a list of the JWE encryption algorithms (enc values) supported by the Authorization Server for the ID Token to encode the Claims in a JWT [JWT].
OPTIONAL. JSON array containing a list of the JWE encryption algorithms (enc values) supported by the Authorization Server for the ID Token to encode the Claims in a JWT [JWT].
request_object_signing_alg_values_supported
OPTIONAL. JSON array containing a list of the JWS signing algorithms (alg values) supported by the Authorization Server for the Request Object described in Section 2.9 of OpenID Connect Messages 1.0 [OpenID.Messages]. These algorithms are used both when the Request Object is passed by value (using the request parameter) and when it is passed by reference (using the request_uri parameter). Servers SHOULD support none and RS256.
OPTIONAL. JSON array containing a list of the JWS signing algorithms (alg values) supported by the Authorization Server for the Request Object described in Section 2.9 of OpenID Connect Messages 1.0 [OpenID.Messages]. These algorithms are used both when the Request Object is passed by value (using the request parameter) and when it is passed by reference (using the request_uri parameter). Servers SHOULD support none and RS256.
request_object_encryption_alg_values_supported
OPTIONAL. JSON array containing a list of the JWE encryption algorithms (alg values) supported by the Authorization Server for the Request Object described in Section 2.9 of OpenID Connect Messages 1.0 [OpenID.Messages]. These algorithms are used both when the Request Object is passed by value and when it is passed by reference.
OPTIONAL. JSON array containing a list of the JWE encryption algorithms (alg values) supported by the Authorization Server for the Request Object described in Section 2.9 of OpenID Connect Messages 1.0 [OpenID.Messages]. These algorithms are used both when the Request Object is passed by value and when it is passed by reference.
request_object_encryption_enc_values_supported
OPTIONAL. JSON array containing a list of the JWE encryption algorithms (enc values) supported by the Authorization Server for the Request Object described in Section 2.9 of OpenID Connect Messages 1.0 [OpenID.Messages]. These algorithms are used both when the Request Object is passed by value and when it is passed by reference.
OPTIONAL. JSON array containing a list of the JWE encryption algorithms (enc values) supported by the Authorization Server for the Request Object described in Section 2.9 of OpenID Connect Messages 1.0 [OpenID.Messages]. These algorithms are used both when the Request Object is passed by value and when it is passed by reference.
token_endpoint_auth_methods_supported
OPTIONAL. JSON array containing a list of authentication methods supported by this Token Endpoint. The options are client_secret_post, client_secret_basic, client_secret_jwt, and private_key_jwt, as described in Section 2.2.1 of OpenID Connect Messages 1.0 [OpenID.Messages]. Other authentication methods may be defined by extensions. If omitted, the default is client_secret_basic -- the HTTP Basic Authentication Scheme as specified in Section 2.3.1 of OAuth 2.0 [RFC6749].
OPTIONAL. JSON array containing a list of authentication methods supported by this Token Endpoint. The options are client_secret_post, client_secret_basic, client_secret_jwt, and private_key_jwt, as described in Section 2.2.1 of OpenID Connect Messages 1.0 [OpenID.Messages]. Other authentication methods may be defined by extensions. If omitted, the default is client_secret_basic -- the HTTP Basic Authentication Scheme as specified in Section 2.3.1 of OAuth 2.0 [RFC6749].
token_endpoint_auth_signing_alg_values_supported
OPTIONAL. JSON array containing a list of the JWS signing algorithms (alg values) supported by the Token Endpoint for the private_key_jwt and client_secret_jwt methods to encode the JWT [JWT]. Servers SHOULD support RS256.
OPTIONAL. JSON array containing a list of the JWS signing algorithms (alg values) supported by the Token Endpoint for the private_key_jwt and client_secret_jwt methods to encode the JWT [JWT]. Servers SHOULD support RS256.
display_values_supported
OPTIONAL. JSON array containing a list of the display parameter values that the OpenID Provider supports. These values are described in Section 2.1.1 of OpenID Connect Messages 1.0 [OpenID.Messages].
OPTIONAL. JSON array containing a list of the display parameter values that the OpenID Provider supports. These values are described in Section 2.1.1 of OpenID Connect Messages 1.0 [OpenID.Messages].
claim_types_supported
OPTIONAL. JSON array containing a list of the Claim Types that the OpenID Provider supports. These Claim Types are described in Section 2.6 of OpenID Connect Messages 1.0 [OpenID.Messages]. Values defined by this specification are normal, aggregated, and distributed. If not specified, the implementation supports only normal Claims.
OPTIONAL. JSON array containing a list of the Claim Types that the OpenID Provider supports. These Claim Types are described in Section 2.6 of OpenID Connect Messages 1.0 [OpenID.Messages]. Values defined by this specification are normal, aggregated, and distributed. If not specified, the implementation supports only normal Claims.
claims_supported
RECOMMENDED. JSON array containing a list of the Claim Names of the Claims that the OpenID Provider may be able to supply values for. Note that for privacy or other reasons, this may not be an exhaustive list.
RECOMMENDED. JSON array containing a list of the Claim Names of the Claims that the OpenID Provider may be able to supply values for. Note that for privacy or other reasons, this may not be an exhaustive list.
service_documentation
OPTIONAL. URL of a page containing human-readable information that developers might want or need to know when using the OpenID Provider. In particular, if the OpenID Provider does not support Dynamic Client Registration, then information on how to register Clients should be provided in this documentation.
OPTIONAL. URL of a page containing human-readable information that developers might want or need to know when using the OpenID Provider. In particular, if the OpenID Provider does not support Dynamic Client Registration, then information on how to register Clients should be provided in this documentation.
claims_locales_supported
OPTIONAL. Languages and scripts supported for values in Claims being returned, represented as a JSON array of BCP47 [RFC5646] language tag values. Not all languages and scripts may be supported for all Claim values.
OPTIONAL. Languages and scripts supported for values in Claims being returned, represented as a JSON array of BCP47 [RFC5646] language tag values. Not all languages and scripts may be supported for all Claim values.
ui_locales_supported
OPTIONAL. Languages and scripts supported for the user interface, represented as a JSON array of BCP47 [RFC5646] language tag values.
OPTIONAL. Languages and scripts supported for the user interface, represented as a JSON array of BCP47 [RFC5646] language tag values.
claims_parameter_supported
OPTIONAL. Boolean value specifying whether the OP supports use of the claims parameter, with true indicating support. If omitted, the default value is false.
OPTIONAL. Boolean value specifying whether the OP supports use of the claims parameter, with true indicating support. If omitted, the default value is false.
request_parameter_supported
OPTIONAL. Boolean value specifying whether the OP supports use of the request parameter, with true indicating support. If omitted, the default value is false.
OPTIONAL. Boolean value specifying whether the OP supports use of the request parameter, with true indicating support. If omitted, the default value is false.
request_uri_parameter_supported
OPTIONAL. Boolean value specifying whether the OP supports use of the request_uri parameter, with true indicating support. If omitted, the default value is true.
OPTIONAL. Boolean value specifying whether the OP supports use of the request_uri parameter, with true indicating support. If omitted, the default value is true.
require_request_uri_registration
OPTIONAL. Boolean value specifying whether the OP requires any request_uri values used to be pre-registered using the request_uris registration parameter. Pre-registration is REQUIRED when the value is true.
OPTIONAL. Boolean value specifying whether the OP requires any request_uri values used to be pre-registered using the request_uris registration parameter. Pre-registration is REQUIRED when the value is true.
op_policy_uri
OPTIONAL. URL that the OpenID Provider provides to the person registering the Client to read about the OP's requirements on how the Relying Party may use the data provided by the OP. The registration process SHOULD display this URL to the person registering the Client if it is given.
OPTIONAL. URL that the OpenID Provider provides to the person registering the Client to read about the OP's requirements on how the Relying Party may use the data provided by the OP. The registration process SHOULD display this URL to the person registering the Client if it is given.
op_tos_uri
OPTIONAL. URL that the OpenID Provider provides to the person registering the Client to read about OpenID Provider's terms of service. The registration process SHOULD display this URL to the person registering the Client if it is given. *
*/
String baseUrl = config.getIssuer();
if (!baseUrl.endsWith("/")) {
logger.warn("Configured issuer doesn't end in /, adding for discovery: " + baseUrl);
baseUrl = baseUrl.concat("/");
@ -242,25 +241,25 @@ public class DiscoveryEndpoint {
//display_types_supported
m.put("claim_types_supported", Lists.newArrayList("normal" /*, "aggregated", "distributed"*/));
m.put("claims_supported", Lists.newArrayList(
"sub",
"name",
"preferred_username",
"given_name",
"family_name",
"middle_name",
"nickname",
"profile",
"picture",
"website",
"gender",
"zone_info",
"locale",
"updated_time",
"birthdate",
"email",
"email_verified",
"phone_number",
"address"
"sub",
"name",
"preferred_username",
"given_name",
"family_name",
"middle_name",
"nickname",
"profile",
"picture",
"website",
"gender",
"zone_info",
"locale",
"updated_time",
"birthdate",
"email",
"email_verified",
"phone_number",
"address"
));
m.put("service_documentation", baseUrl + "about");
//claims_locales_supported
@ -271,11 +270,11 @@ public class DiscoveryEndpoint {
m.put("require_request_uri_registration", false);
m.put("op_policy_uri", baseUrl + "about");
m.put("op_tos_uri", baseUrl + "about");
model.addAttribute("entity", m);
return "jsonEntityView";
}
}

View File

@ -18,13 +18,13 @@ package org.mitre.oauth2.exception;
public class DuplicateClientIdException extends RuntimeException {
public DuplicateClientIdException(String clientId) {
super("Duplicate client id: " + clientId);
}
super("Duplicate client id: " + clientId);
}
/**
*
*/
private static final long serialVersionUID = 1L;
*
*/
private static final long serialVersionUID = 1L;
}

View File

@ -17,7 +17,7 @@ public class JpaAuthenticationHolderRepository implements AuthenticationHolderRe
@PersistenceContext
private EntityManager manager;
@Override
public AuthenticationHolderEntity getById(Long id) {
return manager.find(AuthenticationHolderEntity.class, id);

View File

@ -27,16 +27,16 @@ public class JpaAuthorizationCodeRepository implements AuthorizationCodeReposito
@PersistenceContext
EntityManager manager;
/* (non-Javadoc)
* @see org.mitre.oauth2.repository.AuthorizationCodeRepository#save(org.mitre.oauth2.model.AuthorizationCodeEntity)
*/
@Override
@Transactional
public AuthorizationCodeEntity save(AuthorizationCodeEntity authorizationCode) {
return JpaUtil.saveOrUpdate(authorizationCode.getId(), manager, authorizationCode);
}
/* (non-Javadoc)
@ -45,20 +45,20 @@ public class JpaAuthorizationCodeRepository implements AuthorizationCodeReposito
@Override
@Transactional
public AuthorizationRequestHolder consume(String code) throws InvalidGrantException {
TypedQuery<AuthorizationCodeEntity> query = manager.createNamedQuery("AuthorizationCodeEntity.getByValue", AuthorizationCodeEntity.class);
query.setParameter("code", code);
AuthorizationCodeEntity result = JpaUtil.getSingleResult(query.getResultList());
if (result == null) {
throw new InvalidGrantException("JpaAuthorizationCodeRepository: no authorization code found for value " + code);
}
AuthorizationRequestHolder authRequest = result.getAuthorizationRequestHolder();
manager.remove(result);
return authRequest;
}

View File

@ -37,15 +37,16 @@ public class JpaOAuth2ClientRepository implements OAuth2ClientRepository {
@PersistenceContext
private EntityManager manager;
public JpaOAuth2ClientRepository() {
}
public JpaOAuth2ClientRepository(EntityManager manager) {
this.manager = manager;
}
@Override
public ClientDetailsEntity getById(Long id) {
return manager.find(ClientDetailsEntity.class, id);
}
@ -82,17 +83,17 @@ public class JpaOAuth2ClientRepository implements OAuth2ClientRepository {
}
@Override
public ClientDetailsEntity updateClient(Long id, ClientDetailsEntity client) {
public ClientDetailsEntity updateClient(Long id, ClientDetailsEntity client) {
// sanity check
client.setId(id);
return JpaUtil.saveOrUpdate(id, manager, client);
}
return JpaUtil.saveOrUpdate(id, manager, client);
}
@Override
public Collection<ClientDetailsEntity> getAllClients() {
public Collection<ClientDetailsEntity> getAllClients() {
TypedQuery<ClientDetailsEntity> query = manager.createNamedQuery("ClientDetailsEntity.findAll", ClientDetailsEntity.class);
return query.getResultList();
}
}
}

View File

@ -42,18 +42,18 @@ public class JpaOAuth2TokenRepository implements OAuth2TokenRepository {
query.setParameter("tokenValue", accessTokenValue);
return JpaUtil.getSingleResult(query.getResultList());
}
@Override
public OAuth2AccessTokenEntity getAccessTokenById(Long id) {
return manager.find(OAuth2AccessTokenEntity.class, id);
}
@Override
@Transactional
public OAuth2AccessTokenEntity saveAccessToken(OAuth2AccessTokenEntity token) {
return JpaUtil.saveOrUpdate(token.getId(), manager, token);
}
@Override
@Transactional
public void removeAccessToken(OAuth2AccessTokenEntity accessToken) {
@ -64,17 +64,17 @@ public class JpaOAuth2TokenRepository implements OAuth2TokenRepository {
throw new IllegalArgumentException("Access token not found: " + accessToken);
}
}
@Override
@Transactional
public void clearAccessTokensForRefreshToken(OAuth2RefreshTokenEntity refreshToken) {
public void clearAccessTokensForRefreshToken(OAuth2RefreshTokenEntity refreshToken) {
TypedQuery<OAuth2AccessTokenEntity> query = manager.createNamedQuery("OAuth2AccessTokenEntity.getByRefreshToken", OAuth2AccessTokenEntity.class);
query.setParameter("refreshToken", refreshToken);
List<OAuth2AccessTokenEntity> accessTokens = query.getResultList();
for (OAuth2AccessTokenEntity accessToken : accessTokens) {
removeAccessToken(accessToken);
}
}
List<OAuth2AccessTokenEntity> accessTokens = query.getResultList();
for (OAuth2AccessTokenEntity accessToken : accessTokens) {
removeAccessToken(accessToken);
}
}
@Override
public OAuth2RefreshTokenEntity getRefreshTokenByValue(String refreshTokenValue) {
@ -82,105 +82,105 @@ public class JpaOAuth2TokenRepository implements OAuth2TokenRepository {
query.setParameter("tokenValue", refreshTokenValue);
return JpaUtil.getSingleResult(query.getResultList());
}
@Override
public OAuth2RefreshTokenEntity getRefreshTokenById(Long id) {
return manager.find(OAuth2RefreshTokenEntity.class, id);
}
@Override
@Transactional
public OAuth2RefreshTokenEntity saveRefreshToken(OAuth2RefreshTokenEntity refreshToken) {
return JpaUtil.saveOrUpdate(refreshToken.getId(), manager, refreshToken);
}
@Override
@Transactional
public void removeRefreshToken(OAuth2RefreshTokenEntity refreshToken) {
public void removeRefreshToken(OAuth2RefreshTokenEntity refreshToken) {
OAuth2RefreshTokenEntity found = getRefreshTokenByValue(refreshToken.getValue());
if (found != null) {
manager.remove(found);
} else {
throw new IllegalArgumentException("Refresh token not found: " + refreshToken);
}
}
}
}
@Override
@Transactional
public void clearTokensForClient(ClientDetailsEntity client) {
public void clearTokensForClient(ClientDetailsEntity client) {
TypedQuery<OAuth2AccessTokenEntity> queryA = manager.createNamedQuery("OAuth2AccessTokenEntity.getByClient", OAuth2AccessTokenEntity.class);
queryA.setParameter("client", client);
List<OAuth2AccessTokenEntity> accessTokens = queryA.getResultList();
for (OAuth2AccessTokenEntity accessToken : accessTokens) {
removeAccessToken(accessToken);
}
List<OAuth2AccessTokenEntity> accessTokens = queryA.getResultList();
for (OAuth2AccessTokenEntity accessToken : accessTokens) {
removeAccessToken(accessToken);
}
TypedQuery<OAuth2RefreshTokenEntity> queryR = manager.createNamedQuery("OAuth2RefreshTokenEntity.getByClient", OAuth2RefreshTokenEntity.class);
queryR.setParameter("client", client);
List<OAuth2RefreshTokenEntity> refreshTokens = queryR.getResultList();
for (OAuth2RefreshTokenEntity refreshToken : refreshTokens) {
removeRefreshToken(refreshToken);
}
}
List<OAuth2RefreshTokenEntity> refreshTokens = queryR.getResultList();
for (OAuth2RefreshTokenEntity refreshToken : refreshTokens) {
removeRefreshToken(refreshToken);
}
}
/* (non-Javadoc)
* @see org.mitre.oauth2.repository.OAuth2TokenRepository#getAccessTokensForClient(org.mitre.oauth2.model.ClientDetailsEntity)
*/
@Override
public List<OAuth2AccessTokenEntity> getAccessTokensForClient(ClientDetailsEntity client) {
* @see org.mitre.oauth2.repository.OAuth2TokenRepository#getAccessTokensForClient(org.mitre.oauth2.model.ClientDetailsEntity)
*/
@Override
public List<OAuth2AccessTokenEntity> getAccessTokensForClient(ClientDetailsEntity client) {
TypedQuery<OAuth2AccessTokenEntity> queryA = manager.createNamedQuery("OAuth2AccessTokenEntity.getByClient", OAuth2AccessTokenEntity.class);
queryA.setParameter("client", client);
List<OAuth2AccessTokenEntity> accessTokens = queryA.getResultList();
return accessTokens;
}
List<OAuth2AccessTokenEntity> accessTokens = queryA.getResultList();
return accessTokens;
}
/* (non-Javadoc)
* @see org.mitre.oauth2.repository.OAuth2TokenRepository#getRefreshTokensForClient(org.mitre.oauth2.model.ClientDetailsEntity)
*/
@Override
public List<OAuth2RefreshTokenEntity> getRefreshTokensForClient(ClientDetailsEntity client) {
* @see org.mitre.oauth2.repository.OAuth2TokenRepository#getRefreshTokensForClient(org.mitre.oauth2.model.ClientDetailsEntity)
*/
@Override
public List<OAuth2RefreshTokenEntity> getRefreshTokensForClient(ClientDetailsEntity client) {
TypedQuery<OAuth2RefreshTokenEntity> queryR = manager.createNamedQuery("OAuth2RefreshTokenEntity.getByClient", OAuth2RefreshTokenEntity.class);
queryR.setParameter("client", client);
List<OAuth2RefreshTokenEntity> refreshTokens = queryR.getResultList();
return refreshTokens;
}
List<OAuth2RefreshTokenEntity> refreshTokens = queryR.getResultList();
return refreshTokens;
}
/* (non-Javadoc)
* @see org.mitre.oauth2.repository.OAuth2TokenRepository#getExpiredAccessTokens()
*/
@Override
public List<OAuth2AccessTokenEntity> getExpiredAccessTokens() {
* @see org.mitre.oauth2.repository.OAuth2TokenRepository#getExpiredAccessTokens()
*/
@Override
public List<OAuth2AccessTokenEntity> getExpiredAccessTokens() {
TypedQuery<OAuth2AccessTokenEntity> queryA = manager.createNamedQuery("OAuth2AccessTokenEntity.getExpired", OAuth2AccessTokenEntity.class);
List<OAuth2AccessTokenEntity> accessTokens = queryA.getResultList();
return accessTokens;
}
List<OAuth2AccessTokenEntity> accessTokens = queryA.getResultList();
return accessTokens;
}
/* (non-Javadoc)
* @see org.mitre.oauth2.repository.OAuth2TokenRepository#getExpiredRefreshTokens()
*/
@Override
public List<OAuth2RefreshTokenEntity> getExpiredRefreshTokens() {
* @see org.mitre.oauth2.repository.OAuth2TokenRepository#getExpiredRefreshTokens()
*/
@Override
public List<OAuth2RefreshTokenEntity> getExpiredRefreshTokens() {
TypedQuery<OAuth2RefreshTokenEntity> queryR = manager.createNamedQuery("OAuth2RefreshTokenEntity.getExpired", OAuth2RefreshTokenEntity.class);
List<OAuth2RefreshTokenEntity> refreshTokens = queryR.getResultList();
return refreshTokens;
}
@Override
public OAuth2AccessTokenEntity getByAuthentication(OAuth2Authentication auth) {
TypedQuery<OAuth2AccessTokenEntity> queryA = manager.createNamedQuery("OAuth2AccessTokenEntity.getByAuthentication", OAuth2AccessTokenEntity.class);
queryA.setParameter("authentication", auth);
List<OAuth2AccessTokenEntity> accessTokens = queryA.getResultList();
return JpaUtil.getSingleResult(accessTokens);
}
List<OAuth2RefreshTokenEntity> refreshTokens = queryR.getResultList();
return refreshTokens;
}
@Override
public OAuth2AccessTokenEntity getByAuthentication(OAuth2Authentication auth) {
TypedQuery<OAuth2AccessTokenEntity> queryA = manager.createNamedQuery("OAuth2AccessTokenEntity.getByAuthentication", OAuth2AccessTokenEntity.class);
queryA.setParameter("authentication", auth);
List<OAuth2AccessTokenEntity> accessTokens = queryA.getResultList();
return JpaUtil.getSingleResult(accessTokens);
}
/* (non-Javadoc)
* @see org.mitre.oauth2.repository.OAuth2TokenRepository#getAccessTokenForIdToken(org.mitre.oauth2.model.OAuth2AccessTokenEntity)
*/
@Override
public OAuth2AccessTokenEntity getAccessTokenForIdToken(OAuth2AccessTokenEntity idToken) {
TypedQuery<OAuth2AccessTokenEntity> queryA = manager.createNamedQuery("OAuth2AccessTokenEntity.getByIdToken", OAuth2AccessTokenEntity.class);
queryA.setParameter("idToken", idToken);
List<OAuth2AccessTokenEntity> accessTokens = queryA.getResultList();
return JpaUtil.getSingleResult(accessTokens);
}
* @see org.mitre.oauth2.repository.OAuth2TokenRepository#getAccessTokenForIdToken(org.mitre.oauth2.model.OAuth2AccessTokenEntity)
*/
@Override
public OAuth2AccessTokenEntity getAccessTokenForIdToken(OAuth2AccessTokenEntity idToken) {
TypedQuery<OAuth2AccessTokenEntity> queryA = manager.createNamedQuery("OAuth2AccessTokenEntity.getByIdToken", OAuth2AccessTokenEntity.class);
queryA.setParameter("idToken", idToken);
List<OAuth2AccessTokenEntity> accessTokens = queryA.getResultList();
return JpaUtil.getSingleResult(accessTokens);
}
}

View File

@ -27,7 +27,7 @@ public class JpaSystemScopeRepository implements SystemScopeRepository {
@PersistenceContext
private EntityManager em;
/* (non-Javadoc)
* @see org.mitre.oauth2.repository.SystemScopeRepository#getAll()
*/
@ -35,7 +35,7 @@ public class JpaSystemScopeRepository implements SystemScopeRepository {
@Transactional
public Set<SystemScope> getAll() {
TypedQuery<SystemScope> query = em.createNamedQuery("SystemScope.findAll", SystemScope.class);
return new LinkedHashSet<SystemScope>(query.getResultList());
}
@ -66,7 +66,7 @@ public class JpaSystemScopeRepository implements SystemScopeRepository {
@Transactional
public void remove(SystemScope scope) {
SystemScope found = getById(scope.getId());
if (found != null) {
em.remove(found);
}

View File

@ -23,9 +23,9 @@ public class DefaultOAuth2AuthorizationCodeService implements AuthorizationCodeS
@Autowired
private AuthorizationCodeRepository repository;
private RandomValueStringGenerator generator = new RandomValueStringGenerator();
/**
* Generate a random authorization code and create an AuthorizationCodeEntity,
* which will be stored in the repository.
@ -37,16 +37,16 @@ public class DefaultOAuth2AuthorizationCodeService implements AuthorizationCodeS
@Override
public String createAuthorizationCode(AuthorizationRequestHolder authentication) {
String code = generator.generate();
AuthorizationCodeEntity entity = new AuthorizationCodeEntity(code, authentication);
repository.save(entity);
return code;
}
/**
* Consume a given authorization code.
* Match the provided string to an AuthorizationCodeEntity. If one is found, return
* Consume a given authorization code.
* Match the provided string to an AuthorizationCodeEntity. If one is found, return
* the authentication associated with the code. If one is not found, throw an
* InvalidGrantException.
*
@ -56,7 +56,7 @@ public class DefaultOAuth2AuthorizationCodeService implements AuthorizationCodeS
*/
@Override
public AuthorizationRequestHolder consumeAuthorizationCode(String code) throws InvalidGrantException {
AuthorizationRequestHolder auth = repository.consume(code);
return auth;
}

View File

@ -39,32 +39,32 @@ import com.google.common.base.Strings;
@Service
public class DefaultOAuth2ClientDetailsEntityService implements ClientDetailsEntityService {
@Autowired
private OAuth2ClientRepository clientRepository;
@Autowired
private OAuth2TokenRepository tokenRepository;
@Autowired
private ApprovedSiteService approvedSiteService;
@Autowired
private WhitelistedSiteService whitelistedSiteService;
@Autowired
private BlacklistedSiteService blacklistedSiteService;
public DefaultOAuth2ClientDetailsEntityService() {
}
public DefaultOAuth2ClientDetailsEntityService(OAuth2ClientRepository clientRepository,
public DefaultOAuth2ClientDetailsEntityService(OAuth2ClientRepository clientRepository,
OAuth2TokenRepository tokenRepository) {
this.clientRepository = clientRepository;
this.tokenRepository = tokenRepository;
}
@Override
public ClientDetailsEntity saveNewClient(ClientDetailsEntity client) {
if (client.getId() != null) { // if it's not null, it's already been saved, this is an error
@ -76,37 +76,38 @@ public class DefaultOAuth2ClientDetailsEntityService implements ClientDetailsEnt
if (blacklistedSiteService.isBlacklisted(uri)) {
throw new IllegalArgumentException("Client URI is blacklisted: " + uri);
}
}
}
}
// assign a random clientid if it's empty
// assign a random clientid if it's empty
// NOTE: don't assign a random client secret without asking, since public clients have no secret
if (Strings.isNullOrEmpty(client.getClientId())) {
client = generateClientId(client);
}
// if the client is flagged to allow for refresh tokens, make sure it's got the right granted scopes
if (client.isAllowRefresh()) {
client.getScope().add("offline_access");
} else {
client.getScope().remove("offline_access");
}
// timestamp this to right now
client.setCreatedAt(new Date());
return clientRepository.saveClient(client);
if (Strings.isNullOrEmpty(client.getClientId())) {
client = generateClientId(client);
}
// if the client is flagged to allow for refresh tokens, make sure it's got the right granted scopes
if (client.isAllowRefresh()) {
client.getScope().add("offline_access");
} else {
client.getScope().remove("offline_access");
}
// timestamp this to right now
client.setCreatedAt(new Date());
return clientRepository.saveClient(client);
}
/**
* Get the client by its internal ID
*/
@Override
public ClientDetailsEntity getClientById(Long id) {
ClientDetailsEntity client = clientRepository.getById(id);
return client;
}
/**
* Get the client for the given ClientID
*/
@ -121,87 +122,87 @@ public class DefaultOAuth2ClientDetailsEntityService implements ClientDetailsEnt
return client;
}
}
throw new IllegalArgumentException("Client id must not be empty!");
}
/**
* Delete a client and all its associated tokens
*/
@Override
public void deleteClient(ClientDetailsEntity client) throws InvalidClientException {
public void deleteClient(ClientDetailsEntity client) throws InvalidClientException {
if (clientRepository.getById(client.getId()) == null) {
throw new InvalidClientException("Client with id " + client.getClientId() + " was not found");
}
// clean out any tokens that this client had issued
tokenRepository.clearTokensForClient(client);
// clean out any approved sites for this client
approvedSiteService.clearApprovedSitesForClient(client);
// clear out any whitelisted sites for this client
WhitelistedSite whitelistedSite = whitelistedSiteService.getByClientId(client.getClientId());
if (whitelistedSite != null) {
whitelistedSiteService.remove(whitelistedSite);
whitelistedSiteService.remove(whitelistedSite);
}
// take care of the client itself
clientRepository.deleteClient(client);
}
/**
* Update the oldClient with information from the newClient. The
* Update the oldClient with information from the newClient. The
* id from oldClient is retained.
*/
@Override
public ClientDetailsEntity updateClient(ClientDetailsEntity oldClient, ClientDetailsEntity newClient) throws IllegalArgumentException {
public ClientDetailsEntity updateClient(ClientDetailsEntity oldClient, ClientDetailsEntity newClient) throws IllegalArgumentException {
if (oldClient != null && newClient != null) {
for (String uri : newClient.getRegisteredRedirectUri()) {
if (blacklistedSiteService.isBlacklisted(uri)) {
throw new IllegalArgumentException("Client URI is blacklisted: " + uri);
}
}
// if the client is flagged to allow for refresh tokens, make sure it's got the right scope
if (newClient.isAllowRefresh()) {
newClient.getScope().add("offline_access");
} else {
newClient.getScope().remove("offline_access");
}
}
return clientRepository.updateClient(oldClient.getId(), newClient);
// if the client is flagged to allow for refresh tokens, make sure it's got the right scope
if (newClient.isAllowRefresh()) {
newClient.getScope().add("offline_access");
} else {
newClient.getScope().remove("offline_access");
}
return clientRepository.updateClient(oldClient.getId(), newClient);
}
throw new IllegalArgumentException("Neither old client or new client can be null!");
}
}
/**
* Get all clients in the system
*/
@Override
public Collection<ClientDetailsEntity> getAllClients() {
public Collection<ClientDetailsEntity> getAllClients() {
return clientRepository.getAllClients();
}
}
/**
* Generates a clientId for the given client and sets it to the client's clientId field. Returns the client that was passed in, now with id set.
*/
@Override
public ClientDetailsEntity generateClientId(ClientDetailsEntity client) {
public ClientDetailsEntity generateClientId(ClientDetailsEntity client) {
client.setClientId(UUID.randomUUID().toString());
return client;
}
return client;
}
/**
* Generates a new clientSecret for the given client and sets it to the client's clientSecret field. Returns the client that was passed in, now with secret set.
*/
@Override
public ClientDetailsEntity generateClientSecret(ClientDetailsEntity client) {
public ClientDetailsEntity generateClientSecret(ClientDetailsEntity client) {
client.setClientSecret(Base64.encodeBase64URLSafeString(new BigInteger(512, new SecureRandom()).toByteArray()).replace("=", ""));
return client;
}
return client;
}
}

View File

@ -18,16 +18,12 @@
*/
package org.mitre.oauth2.service.impl;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.mitre.oauth2.exception.NonceReuseException;
import org.mitre.oauth2.model.AuthenticationHolderEntity;
import org.mitre.oauth2.model.ClientDetailsEntity;
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
@ -36,8 +32,6 @@ import org.mitre.oauth2.repository.AuthenticationHolderRepository;
import org.mitre.oauth2.repository.OAuth2TokenRepository;
import org.mitre.oauth2.service.ClientDetailsEntityService;
import org.mitre.oauth2.service.OAuth2TokenEntityService;
import org.mitre.openid.connect.model.Nonce;
import org.mitre.openid.connect.service.NonceService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -62,142 +56,142 @@ import com.nimbusds.jwt.PlainJWT;
*/
@Service
public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityService {
private static Logger logger = LoggerFactory.getLogger(DefaultOAuth2ProviderTokenService.class);
@Autowired
private OAuth2TokenRepository tokenRepository;
@Autowired
private AuthenticationHolderRepository authenticationHolderRepository;
@Autowired
private ClientDetailsEntityService clientDetailsService;
@Autowired
private TokenEnhancer tokenEnhancer;
@Override
public OAuth2AccessTokenEntity createAccessToken(OAuth2Authentication authentication) throws AuthenticationException, InvalidClientException {
public OAuth2AccessTokenEntity createAccessToken(OAuth2Authentication authentication) throws AuthenticationException, InvalidClientException {
if (authentication != null && authentication.getAuthorizationRequest() != null) {
// look up our client
AuthorizationRequest clientAuth = authentication.getAuthorizationRequest();
ClientDetailsEntity client = clientDetailsService.loadClientByClientId(clientAuth.getClientId());
if (client == null) {
throw new InvalidClientException("Client not found: " + clientAuth.getClientId());
}
OAuth2AccessTokenEntity token = new OAuth2AccessTokenEntity();//accessTokenFactory.createNewAccessToken();
// attach the client
token.setClient(client);
// inherit the scope from the auth, but make a new set so it is
//not unmodifiable. Unmodifiables don't play nicely with Eclipselink, which
//wants to use the clone operation.
Set<String> scopes = Sets.newHashSet(clientAuth.getScope());
token.setScope(scopes);
// make it expire if necessary
if (client.getAccessTokenValiditySeconds() != null && client.getAccessTokenValiditySeconds() > 0) {
Date expiration = new Date(System.currentTimeMillis() + (client.getAccessTokenValiditySeconds() * 1000L));
token.setExpiration(expiration);
}
// attach the authorization so that we can look it up later
AuthenticationHolderEntity authHolder = new AuthenticationHolderEntity();
authHolder.setAuthentication(authentication);
authHolder = authenticationHolderRepository.save(authHolder);
token.setAuthenticationHolder(authHolder);
// attach a refresh token, if this client is allowed to request them and the user gets the offline scope
// TODO: tie this to some kind of scope service
if (client.isAllowRefresh() && scopes.contains("offline_access")) {
OAuth2RefreshTokenEntity refreshToken = new OAuth2RefreshTokenEntity(); //refreshTokenFactory.createNewRefreshToken();
JWTClaimsSet refreshClaims = new JWTClaimsSet();
// attach the client
token.setClient(client);
// make it expire if necessary
if (client.getRefreshTokenValiditySeconds() != null) {
Date expiration = new Date(System.currentTimeMillis() + (client.getRefreshTokenValiditySeconds() * 1000L));
refreshToken.setExpiration(expiration);
refreshClaims.setExpirationTime(expiration);
}
// set a random identifier
refreshClaims.setJWTID(UUID.randomUUID().toString());
// inherit the scope from the auth, but make a new set so it is
//not unmodifiable. Unmodifiables don't play nicely with Eclipselink, which
//wants to use the clone operation.
Set<String> scopes = Sets.newHashSet(clientAuth.getScope());
token.setScope(scopes);
// TODO: add issuer fields, signature to JWT
PlainJWT refreshJwt = new PlainJWT(refreshClaims);
refreshToken.setJwt(refreshJwt);
//Add the authentication
refreshToken.setAuthenticationHolder(authHolder);
refreshToken.setClient(client);
// save the token first so that we can set it to a member of the access token (NOTE: is this step necessary?)
tokenRepository.saveRefreshToken(refreshToken);
token.setRefreshToken(refreshToken);
}
// make it expire if necessary
if (client.getAccessTokenValiditySeconds() != null && client.getAccessTokenValiditySeconds() > 0) {
Date expiration = new Date(System.currentTimeMillis() + (client.getAccessTokenValiditySeconds() * 1000L));
token.setExpiration(expiration);
}
tokenEnhancer.enhance(token, authentication);
tokenRepository.saveAccessToken(token);
if (token.getRefreshToken() != null) {
tokenRepository.saveRefreshToken(token.getRefreshToken()); // make sure we save any changes that might have been enhanced
}
return token;
// attach the authorization so that we can look it up later
AuthenticationHolderEntity authHolder = new AuthenticationHolderEntity();
authHolder.setAuthentication(authentication);
authHolder = authenticationHolderRepository.save(authHolder);
token.setAuthenticationHolder(authHolder);
// attach a refresh token, if this client is allowed to request them and the user gets the offline scope
// TODO: tie this to some kind of scope service
if (client.isAllowRefresh() && scopes.contains("offline_access")) {
OAuth2RefreshTokenEntity refreshToken = new OAuth2RefreshTokenEntity(); //refreshTokenFactory.createNewRefreshToken();
JWTClaimsSet refreshClaims = new JWTClaimsSet();
// make it expire if necessary
if (client.getRefreshTokenValiditySeconds() != null) {
Date expiration = new Date(System.currentTimeMillis() + (client.getRefreshTokenValiditySeconds() * 1000L));
refreshToken.setExpiration(expiration);
refreshClaims.setExpirationTime(expiration);
}
// set a random identifier
refreshClaims.setJWTID(UUID.randomUUID().toString());
// TODO: add issuer fields, signature to JWT
PlainJWT refreshJwt = new PlainJWT(refreshClaims);
refreshToken.setJwt(refreshJwt);
//Add the authentication
refreshToken.setAuthenticationHolder(authHolder);
refreshToken.setClient(client);
// save the token first so that we can set it to a member of the access token (NOTE: is this step necessary?)
tokenRepository.saveRefreshToken(refreshToken);
token.setRefreshToken(refreshToken);
}
tokenEnhancer.enhance(token, authentication);
tokenRepository.saveAccessToken(token);
if (token.getRefreshToken() != null) {
tokenRepository.saveRefreshToken(token.getRefreshToken()); // make sure we save any changes that might have been enhanced
}
return token;
}
throw new AuthenticationCredentialsNotFoundException("No authentication credentials found");
}
throw new AuthenticationCredentialsNotFoundException("No authentication credentials found");
}
@Override
public OAuth2AccessTokenEntity refreshAccessToken(String refreshTokenValue, AuthorizationRequest authRequest) throws AuthenticationException {
public OAuth2AccessTokenEntity refreshAccessToken(String refreshTokenValue, AuthorizationRequest authRequest) throws AuthenticationException {
OAuth2RefreshTokenEntity refreshToken = tokenRepository.getRefreshTokenByValue(refreshTokenValue);
if (refreshToken == null) {
throw new InvalidTokenException("Invalid refresh token: " + refreshTokenValue);
}
ClientDetailsEntity client = refreshToken.getClient();
AuthenticationHolderEntity authHolder = refreshToken.getAuthenticationHolder();
//Make sure this client allows access token refreshing
if (!client.isAllowRefresh()) {
throw new InvalidClientException("Client does not allow refreshing access token!");
}
// clear out any access tokens
// TODO: make this a configurable option
tokenRepository.clearAccessTokensForRefreshToken(refreshToken);
if (refreshToken.isExpired()) {
tokenRepository.removeRefreshToken(refreshToken);
throw new InvalidTokenException("Expired refresh token: " + refreshTokenValue);
throw new InvalidTokenException("Expired refresh token: " + refreshTokenValue);
}
// TODO: have the option to recycle the refresh token here, too
// for now, we just reuse it as long as it's valid, which is the original intent
OAuth2AccessTokenEntity token = new OAuth2AccessTokenEntity();
OAuth2AccessTokenEntity token = new OAuth2AccessTokenEntity();
// get the stored scopes from the authentication holder's authorization request; these are the scopes associated with the refresh token
Set<String> refreshScopes = new HashSet<String>(refreshToken.getAuthenticationHolder().getAuthentication().getAuthorizationRequest().getScope());
Set<String> scope = new HashSet<String>(authRequest.getScope());
if (scope != null && !scope.isEmpty()) {
if (scope != null && !scope.isEmpty()) {
// ensure a proper subset of scopes
if (refreshScopes != null && refreshScopes.containsAll(scope)) {
// set the scope of the new access token if requested
@ -211,189 +205,189 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi
// otherwise inherit the scope of the refresh token (if it's there -- this can return a null scope set)
token.setScope(refreshScopes);
}
token.setClient(client);
if (client.getAccessTokenValiditySeconds() != null) {
Date expiration = new Date(System.currentTimeMillis() + (client.getAccessTokenValiditySeconds() * 1000L));
token.setExpiration(expiration);
}
token.setRefreshToken(refreshToken);
token.setAuthenticationHolder(authHolder);
tokenEnhancer.enhance(token, authHolder.getAuthentication());
tokenRepository.saveAccessToken(token);
return token;
}
token.setClient(client);
if (client.getAccessTokenValiditySeconds() != null) {
Date expiration = new Date(System.currentTimeMillis() + (client.getAccessTokenValiditySeconds() * 1000L));
token.setExpiration(expiration);
}
token.setRefreshToken(refreshToken);
token.setAuthenticationHolder(authHolder);
tokenEnhancer.enhance(token, authHolder.getAuthentication());
tokenRepository.saveAccessToken(token);
return token;
}
@Override
public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException {
public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException {
OAuth2AccessTokenEntity accessToken = tokenRepository.getAccessTokenByValue(accessTokenValue);
if (accessToken == null) {
throw new InvalidTokenException("Invalid access token: " + accessTokenValue);
}
if (accessToken.isExpired()) {
//tokenRepository.removeAccessToken(accessToken);
revokeAccessToken(accessToken);
throw new InvalidTokenException("Expired access token: " + accessTokenValue);
}
return accessToken.getAuthenticationHolder().getAuthentication();
}
return accessToken.getAuthenticationHolder().getAuthentication();
}
/**
* Get an access token from its token value.
*/
@Override
public OAuth2AccessTokenEntity readAccessToken(String accessTokenValue) throws AuthenticationException {
public OAuth2AccessTokenEntity readAccessToken(String accessTokenValue) throws AuthenticationException {
OAuth2AccessTokenEntity accessToken = tokenRepository.getAccessTokenByValue(accessTokenValue);
if (accessToken == null) {
throw new InvalidTokenException("Access token for value " + accessTokenValue + " was not found");
}
else {
return accessToken;
return accessToken;
}
}
}
/**
* Get an access token by its authentication object.
*/
@Override
public OAuth2AccessTokenEntity getAccessToken(OAuth2Authentication authentication) {
OAuth2AccessTokenEntity accessToken = tokenRepository.getByAuthentication(authentication);
return accessToken;
}
/**
* Get a refresh token by its token value.
*/
@Override
public OAuth2RefreshTokenEntity getRefreshToken(String refreshTokenValue) throws AuthenticationException {
public OAuth2RefreshTokenEntity getRefreshToken(String refreshTokenValue) throws AuthenticationException {
OAuth2RefreshTokenEntity refreshToken = tokenRepository.getRefreshTokenByValue(refreshTokenValue);
if (refreshToken == null) {
throw new InvalidTokenException("Refresh token for value " + refreshTokenValue + " was not found");
}
else {
return refreshToken;
return refreshToken;
}
}
}
/**
* Revoke a refresh token and all access tokens issued to it.
*/
@Override
public void revokeRefreshToken(OAuth2RefreshTokenEntity refreshToken) {
tokenRepository.clearAccessTokensForRefreshToken(refreshToken);
tokenRepository.removeRefreshToken(refreshToken);
}
public void revokeRefreshToken(OAuth2RefreshTokenEntity refreshToken) {
tokenRepository.clearAccessTokensForRefreshToken(refreshToken);
tokenRepository.removeRefreshToken(refreshToken);
}
/**
* Revoke an access token.
* Revoke an access token.
*/
@Override
public void revokeAccessToken(OAuth2AccessTokenEntity accessToken) {
tokenRepository.removeAccessToken(accessToken);
}
public void revokeAccessToken(OAuth2AccessTokenEntity accessToken) {
tokenRepository.removeAccessToken(accessToken);
}
/* (non-Javadoc)
* @see org.mitre.oauth2.service.OAuth2TokenEntityService#getAccessTokensForClient(org.mitre.oauth2.model.ClientDetailsEntity)
*/
@Override
public List<OAuth2AccessTokenEntity> getAccessTokensForClient(ClientDetailsEntity client) {
return tokenRepository.getAccessTokensForClient(client);
}
* @see org.mitre.oauth2.service.OAuth2TokenEntityService#getAccessTokensForClient(org.mitre.oauth2.model.ClientDetailsEntity)
*/
@Override
public List<OAuth2AccessTokenEntity> getAccessTokensForClient(ClientDetailsEntity client) {
return tokenRepository.getAccessTokensForClient(client);
}
/* (non-Javadoc)
* @see org.mitre.oauth2.service.OAuth2TokenEntityService#getRefreshTokensForClient(org.mitre.oauth2.model.ClientDetailsEntity)
*/
@Override
public List<OAuth2RefreshTokenEntity> getRefreshTokensForClient(ClientDetailsEntity client) {
return tokenRepository.getRefreshTokensForClient(client);
}
* @see org.mitre.oauth2.service.OAuth2TokenEntityService#getRefreshTokensForClient(org.mitre.oauth2.model.ClientDetailsEntity)
*/
@Override
public List<OAuth2RefreshTokenEntity> getRefreshTokensForClient(ClientDetailsEntity client) {
return tokenRepository.getRefreshTokensForClient(client);
}
@Override
@Scheduled(fixedRate = 5 * 60 * 1000) // schedule this task every five minutes
public void clearExpiredTokens() {
logger.info("Cleaning out all expired tokens");
List<OAuth2AccessTokenEntity> accessTokens = tokenRepository.getExpiredAccessTokens();
logger.info("Found " + accessTokens.size() + " expired access tokens");
for (OAuth2AccessTokenEntity oAuth2AccessTokenEntity : accessTokens) {
revokeAccessToken(oAuth2AccessTokenEntity);
}
List<OAuth2RefreshTokenEntity> refreshTokens = tokenRepository.getExpiredRefreshTokens();
logger.info("Found " + refreshTokens.size() + " expired refresh tokens");
for (OAuth2RefreshTokenEntity oAuth2RefreshTokenEntity : refreshTokens) {
revokeRefreshToken(oAuth2RefreshTokenEntity);
}
}
/**
@Override
@Scheduled(fixedRate = 5 * 60 * 1000) // schedule this task every five minutes
public void clearExpiredTokens() {
logger.info("Cleaning out all expired tokens");
List<OAuth2AccessTokenEntity> accessTokens = tokenRepository.getExpiredAccessTokens();
logger.info("Found " + accessTokens.size() + " expired access tokens");
for (OAuth2AccessTokenEntity oAuth2AccessTokenEntity : accessTokens) {
revokeAccessToken(oAuth2AccessTokenEntity);
}
List<OAuth2RefreshTokenEntity> refreshTokens = tokenRepository.getExpiredRefreshTokens();
logger.info("Found " + refreshTokens.size() + " expired refresh tokens");
for (OAuth2RefreshTokenEntity oAuth2RefreshTokenEntity : refreshTokens) {
revokeRefreshToken(oAuth2RefreshTokenEntity);
}
}
/**
* Get a builder object for this class (for tests)
* @return
*/
public static DefaultOAuth2ProviderTokenServicesBuilder makeBuilder() {
return new DefaultOAuth2ProviderTokenServicesBuilder();
}
/**
* Builder class for test harnesses.
*/
public static class DefaultOAuth2ProviderTokenServicesBuilder {
private DefaultOAuth2ProviderTokenService instance;
private DefaultOAuth2ProviderTokenServicesBuilder() {
instance = new DefaultOAuth2ProviderTokenService();
}
public DefaultOAuth2ProviderTokenServicesBuilder setTokenRepository(OAuth2TokenRepository tokenRepository) {
instance.tokenRepository = tokenRepository;
return this;
}
public DefaultOAuth2ProviderTokenServicesBuilder setClientDetailsService(ClientDetailsEntityService clientDetailsService) {
instance.clientDetailsService = clientDetailsService;
return this;
}
public DefaultOAuth2ProviderTokenServicesBuilder setTokenEnhancer(TokenEnhancer tokenEnhancer) {
instance.tokenEnhancer = tokenEnhancer;
return this;
}
public OAuth2TokenEntityService finish() {
return instance;
}
}
/* (non-Javadoc)
* @see org.mitre.oauth2.service.OAuth2TokenEntityService#saveAccessToken(org.mitre.oauth2.model.OAuth2AccessTokenEntity)
*/
@Override
public OAuth2AccessTokenEntity saveAccessToken(OAuth2AccessTokenEntity accessToken) {
return tokenRepository.saveAccessToken(accessToken);
}
* @see org.mitre.oauth2.service.OAuth2TokenEntityService#saveAccessToken(org.mitre.oauth2.model.OAuth2AccessTokenEntity)
*/
@Override
public OAuth2AccessTokenEntity saveAccessToken(OAuth2AccessTokenEntity accessToken) {
return tokenRepository.saveAccessToken(accessToken);
}
/* (non-Javadoc)
* @see org.mitre.oauth2.service.OAuth2TokenEntityService#saveRefreshToken(org.mitre.oauth2.model.OAuth2RefreshTokenEntity)
*/
@Override
public OAuth2RefreshTokenEntity saveRefreshToken(OAuth2RefreshTokenEntity refreshToken) {
return tokenRepository.saveRefreshToken(refreshToken);
}
* @see org.mitre.oauth2.service.OAuth2TokenEntityService#saveRefreshToken(org.mitre.oauth2.model.OAuth2RefreshTokenEntity)
*/
@Override
public OAuth2RefreshTokenEntity saveRefreshToken(OAuth2RefreshTokenEntity refreshToken) {
return tokenRepository.saveRefreshToken(refreshToken);
}
/**
* @return the tokenEnhancer
@ -410,11 +404,11 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi
}
/* (non-Javadoc)
* @see org.mitre.oauth2.service.OAuth2TokenEntityService#getAccessTokenForIdToken(org.mitre.oauth2.model.OAuth2AccessTokenEntity)
*/
@Override
public OAuth2AccessTokenEntity getAccessTokenForIdToken(OAuth2AccessTokenEntity idToken) {
return tokenRepository.getAccessTokenForIdToken(idToken);
}
* @see org.mitre.oauth2.service.OAuth2TokenEntityService#getAccessTokenForIdToken(org.mitre.oauth2.model.OAuth2AccessTokenEntity)
*/
@Override
public OAuth2AccessTokenEntity getAccessTokenForIdToken(OAuth2AccessTokenEntity idToken) {
return tokenRepository.getAccessTokenForIdToken(idToken);
}
}

View File

@ -27,132 +27,132 @@ public class DefaultSystemScopeService implements SystemScopeService {
@Autowired
private SystemScopeRepository repository;
private Predicate<SystemScope> isDefault = new Predicate<SystemScope>() {
@Override
public boolean apply(SystemScope input) {
public boolean apply(SystemScope input) {
return (input != null && input.isDefaultScope());
}
}
};
private Predicate<SystemScope> isDynReg = new Predicate<SystemScope>() {
@Override
public boolean apply(SystemScope input) {
public boolean apply(SystemScope input) {
return (input != null && input.isAllowDynReg());
}
}
};
private Function<String, SystemScope> stringToSystemScope = new Function<String, SystemScope>() {
@Override
public SystemScope apply(String input) {
public SystemScope apply(String input) {
if (input == null) {
return null;
} else {
SystemScope s = getByValue(input);
if (s != null) {
// get the real scope if it's available
return s;
} else {
// make a fake one otherwise
return new SystemScope(input);
}
SystemScope s = getByValue(input);
if (s != null) {
// get the real scope if it's available
return s;
} else {
// make a fake one otherwise
return new SystemScope(input);
}
}
}
}
};
private Function<SystemScope, String> systemScopeToString = new Function<SystemScope, String>() {
@Override
public String apply(SystemScope input) {
public String apply(SystemScope input) {
if (input == null) {
return null;
} else {
return input.getValue();
}
}
}
};
/* (non-Javadoc)
* @see org.mitre.oauth2.service.SystemScopeService#getAll()
*/
@Override
public Set<SystemScope> getAll() {
return repository.getAll();
}
@Override
public Set<SystemScope> getAll() {
return repository.getAll();
}
/* (non-Javadoc)
* @see org.mitre.oauth2.service.SystemScopeService#getDefaults()
*/
@Override
public Set<SystemScope> getDefaults() {
@Override
public Set<SystemScope> getDefaults() {
return Sets.filter(getAll(), isDefault);
}
}
/* (non-Javadoc)
* @see org.mitre.oauth2.service.SystemScopeService#getDynReg()
*/
@Override
public Set<SystemScope> getDynReg() {
return Sets.filter(getAll(), isDynReg);
}
@Override
public Set<SystemScope> getDynReg() {
return Sets.filter(getAll(), isDynReg);
}
/* (non-Javadoc)
* @see org.mitre.oauth2.service.SystemScopeService#getById(java.lang.Long)
*/
@Override
public SystemScope getById(Long id) {
return repository.getById(id);
}
@Override
public SystemScope getById(Long id) {
return repository.getById(id);
}
/* (non-Javadoc)
* @see org.mitre.oauth2.service.SystemScopeService#getByValue(java.lang.String)
*/
@Override
public SystemScope getByValue(String value) {
return repository.getByValue(value);
}
@Override
public SystemScope getByValue(String value) {
return repository.getByValue(value);
}
/* (non-Javadoc)
* @see org.mitre.oauth2.service.SystemScopeService#remove(org.mitre.oauth2.model.SystemScope)
*/
@Override
public void remove(SystemScope scope) {
repository.remove(scope);
}
@Override
public void remove(SystemScope scope) {
repository.remove(scope);
}
/* (non-Javadoc)
* @see org.mitre.oauth2.service.SystemScopeService#save(org.mitre.oauth2.model.SystemScope)
*/
@Override
public SystemScope save(SystemScope scope) {
return repository.save(scope);
}
@Override
public SystemScope save(SystemScope scope) {
return repository.save(scope);
}
/* (non-Javadoc)
* @see org.mitre.oauth2.service.SystemScopeService#fromStrings(java.util.Set)
*/
@Override
public Set<SystemScope> fromStrings(Set<String> scope) {
if (scope == null) {
return null;
} else {
return new LinkedHashSet<SystemScope>(Collections2.filter(Collections2.transform(scope, stringToSystemScope), Predicates.notNull()));
}
}
@Override
public Set<SystemScope> fromStrings(Set<String> scope) {
if (scope == null) {
return null;
} else {
return new LinkedHashSet<SystemScope>(Collections2.filter(Collections2.transform(scope, stringToSystemScope), Predicates.notNull()));
}
}
/* (non-Javadoc)
* @see org.mitre.oauth2.service.SystemScopeService#toStrings(java.util.Set)
*/
@Override
public Set<String> toStrings(Set<SystemScope> scope) {
if (scope == null) {
return null;
} else {
return new LinkedHashSet<String>(Collections2.filter(Collections2.transform(scope, systemScopeToString), Predicates.notNull()));
}
}
@Override
public Set<String> toStrings(Set<SystemScope> scope) {
if (scope == null) {
return null;
} else {
return new LinkedHashSet<String>(Collections2.filter(Collections2.transform(scope, systemScopeToString), Predicates.notNull()));
}
}
}

View File

@ -33,7 +33,7 @@ public class ChainedTokenGranter extends AbstractTokenGranter {
// keep down-cast versions so we can get to the right queries
private OAuth2TokenEntityService tokenServices;
/**
* @param tokenServices
* @param clientDetailsService
@ -46,55 +46,55 @@ public class ChainedTokenGranter extends AbstractTokenGranter {
}
/* (non-Javadoc)
* @see org.springframework.security.oauth2.provider.token.AbstractTokenGranter#getOAuth2Authentication(org.springframework.security.oauth2.provider.AuthorizationRequest)
*/
@Override
protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest authorizationRequest) throws AuthenticationException, InvalidTokenException {
// read and load up the existing token
String incomingTokenValue = authorizationRequest.getAuthorizationParameters().get("token");
OAuth2AccessTokenEntity incomingToken = tokenServices.readAccessToken(incomingTokenValue);
// check for scoping in the request, can't up-scope with a chained request
Set<String> approvedScopes = incomingToken.getScope();
Set<String> requestedScopes = authorizationRequest.getScope();
if (requestedScopes == null) {
requestedScopes = new HashSet<String>();
}
// do a check on the requested scopes -- if they exactly match the client scopes, they were probably shadowed by the token granter
// FIXME: bug in SECOAUTH functionality
ClientDetailsEntity client = incomingToken.getClient();
if (client.getScope().equals(requestedScopes)) {
requestedScopes = new HashSet<String>();
}
// if our scopes are a valid subset of what's allowed, we can continue
if (approvedScopes.containsAll(requestedScopes)) {
* @see org.springframework.security.oauth2.provider.token.AbstractTokenGranter#getOAuth2Authentication(org.springframework.security.oauth2.provider.AuthorizationRequest)
*/
@Override
protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest authorizationRequest) throws AuthenticationException, InvalidTokenException {
// read and load up the existing token
String incomingTokenValue = authorizationRequest.getAuthorizationParameters().get("token");
OAuth2AccessTokenEntity incomingToken = tokenServices.readAccessToken(incomingTokenValue);
// build an appropriate auth request to hand to the token services layer
DefaultAuthorizationRequest outgoingAuthRequest = new DefaultAuthorizationRequest(authorizationRequest);
outgoingAuthRequest.setApproved(true);
if (requestedScopes.isEmpty()) {
// if there are no scopes, inherit the original scopes from the token
outgoingAuthRequest.setScope(approvedScopes);
} else {
// if scopes were asked for, give only the subset of scopes requested
// this allows safe downscoping
outgoingAuthRequest.setScope(Sets.intersection(requestedScopes, approvedScopes));
}
// NOTE: don't revoke the existing access token
// check for scoping in the request, can't up-scope with a chained request
Set<String> approvedScopes = incomingToken.getScope();
Set<String> requestedScopes = authorizationRequest.getScope();
if (requestedScopes == null) {
requestedScopes = new HashSet<String>();
}
// do a check on the requested scopes -- if they exactly match the client scopes, they were probably shadowed by the token granter
// FIXME: bug in SECOAUTH functionality
ClientDetailsEntity client = incomingToken.getClient();
if (client.getScope().equals(requestedScopes)) {
requestedScopes = new HashSet<String>();
}
// if our scopes are a valid subset of what's allowed, we can continue
if (approvedScopes.containsAll(requestedScopes)) {
// build an appropriate auth request to hand to the token services layer
DefaultAuthorizationRequest outgoingAuthRequest = new DefaultAuthorizationRequest(authorizationRequest);
outgoingAuthRequest.setApproved(true);
if (requestedScopes.isEmpty()) {
// if there are no scopes, inherit the original scopes from the token
outgoingAuthRequest.setScope(approvedScopes);
} else {
// if scopes were asked for, give only the subset of scopes requested
// this allows safe downscoping
outgoingAuthRequest.setScope(Sets.intersection(requestedScopes, approvedScopes));
}
// NOTE: don't revoke the existing access token
// create a new access token
OAuth2Authentication authentication = new OAuth2Authentication(outgoingAuthRequest, incomingToken.getAuthenticationHolder().getAuthentication().getUserAuthentication());
return authentication;
} else {
throw new InvalidScopeException("Invalid scope requested in chained request", approvedScopes);
}
}
// create a new access token
OAuth2Authentication authentication = new OAuth2Authentication(outgoingAuthRequest, incomingToken.getAuthenticationHolder().getAuthentication().getUserAuthentication());
return authentication;
} else {
throw new InvalidScopeException("Invalid scope requested in chained request", approvedScopes);
}
}
}

View File

@ -3,7 +3,6 @@
*/
package org.mitre.oauth2.token;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.util.Date;
@ -39,118 +38,118 @@ public class JwtAssertionTokenGranter extends AbstractTokenGranter {
// keep down-cast versions so we can get to the right queries
private OAuth2TokenEntityService tokenServices;
@Autowired
private JwtSigningAndValidationService jwtService;
@Autowired
private ConfigurationPropertiesBean config;
@Autowired
public JwtAssertionTokenGranter(OAuth2TokenEntityService tokenServices, ClientDetailsEntityService clientDetailsService) {
super(tokenServices, clientDetailsService, grantType);
this.tokenServices = tokenServices;
}
super(tokenServices, clientDetailsService, grantType);
this.tokenServices = tokenServices;
}
/* (non-Javadoc)
* @see org.springframework.security.oauth2.provider.token.AbstractTokenGranter#getOAuth2Authentication(org.springframework.security.oauth2.provider.AuthorizationRequest)
*/
@Override
protected OAuth2AccessToken getAccessToken(AuthorizationRequest authorizationRequest) throws AuthenticationException, InvalidTokenException {
// read and load up the existing token
String incomingTokenValue = authorizationRequest.getAuthorizationParameters().get("assertion");
OAuth2AccessTokenEntity incomingToken = tokenServices.readAccessToken(incomingTokenValue);
ClientDetailsEntity client = incomingToken.getClient();
* @see org.springframework.security.oauth2.provider.token.AbstractTokenGranter#getOAuth2Authentication(org.springframework.security.oauth2.provider.AuthorizationRequest)
*/
@Override
protected OAuth2AccessToken getAccessToken(AuthorizationRequest authorizationRequest) throws AuthenticationException, InvalidTokenException {
// read and load up the existing token
String incomingTokenValue = authorizationRequest.getAuthorizationParameters().get("assertion");
OAuth2AccessTokenEntity incomingToken = tokenServices.readAccessToken(incomingTokenValue);
if (incomingToken.getScope().contains(OAuth2AccessTokenEntity.ID_TOKEN_SCOPE)) {
if (!client.getClientId().equals(authorizationRequest.getClientId())) {
throw new InvalidClientException("Not the right client for this token");
}
ClientDetailsEntity client = incomingToken.getClient();
// it's an ID token, process it accordingly
try {
// TODO: make this use a more specific idtoken class
JWT idToken = JWTParser.parse(incomingTokenValue);
OAuth2AccessTokenEntity accessToken = tokenServices.getAccessTokenForIdToken(incomingToken);
if (accessToken != null) {
//OAuth2AccessTokenEntity newIdToken = tokenServices.get
OAuth2AccessTokenEntity newIdTokenEntity = new OAuth2AccessTokenEntity();
// copy over all existing claims
JWTClaimsSet claims = new JWTClaimsSet(idToken.getJWTClaimsSet());
// update expiration and issued-at claims
if (incomingToken.getScope().contains(OAuth2AccessTokenEntity.ID_TOKEN_SCOPE)) {
if (!client.getClientId().equals(authorizationRequest.getClientId())) {
throw new InvalidClientException("Not the right client for this token");
}
// it's an ID token, process it accordingly
try {
// TODO: make this use a more specific idtoken class
JWT idToken = JWTParser.parse(incomingTokenValue);
OAuth2AccessTokenEntity accessToken = tokenServices.getAccessTokenForIdToken(incomingToken);
if (accessToken != null) {
//OAuth2AccessTokenEntity newIdToken = tokenServices.get
OAuth2AccessTokenEntity newIdTokenEntity = new OAuth2AccessTokenEntity();
// copy over all existing claims
JWTClaimsSet claims = new JWTClaimsSet(idToken.getJWTClaimsSet());
// update expiration and issued-at claims
if (client.getIdTokenValiditySeconds() != null) {
Date expiration = new Date(System.currentTimeMillis() + (client.getIdTokenValiditySeconds() * 1000L));
claims.setExpirationTime(expiration);
newIdTokenEntity.setExpiration(expiration);
}
claims.setIssueTime(new Date());
SignedJWT newIdToken = new SignedJWT((JWSHeader) idToken.getHeader(), claims);
jwtService.signJwt(newIdToken);
jwtService.signJwt(newIdToken);
newIdTokenEntity.setJwt(newIdToken);
newIdTokenEntity.setAuthenticationHolder(incomingToken.getAuthenticationHolder());
newIdTokenEntity.setScope(incomingToken.getScope());
newIdTokenEntity.setClient(incomingToken.getClient());
newIdTokenEntity = tokenServices.saveAccessToken(newIdTokenEntity);
// attach the ID token to the access token entity
accessToken.setIdToken(newIdTokenEntity);
accessToken = tokenServices.saveAccessToken(accessToken);
// delete the old ID token
tokenServices.revokeAccessToken(incomingToken);
return newIdTokenEntity;
}
} catch (ParseException e) {
logger.warn("Couldn't parse id token", e);
}
}
// if we got down here, we didn't actually create any tokens, so return null
return null;
/*
* Otherwise, process it like an access token assertion ... which we don't support yet so this is all commented out
* /
return newIdTokenEntity;
}
} catch (ParseException e) {
logger.warn("Couldn't parse id token", e);
}
}
// if we got down here, we didn't actually create any tokens, so return null
return null;
/*
* Otherwise, process it like an access token assertion ... which we don't support yet so this is all commented out
* /
if (jwtService.validateSignature(incomingTokenValue)) {
Jwt jwt = Jwt.parse(incomingTokenValue);
if (oldToken.getScope().contains("id-token")) {
// TODO: things
}
// TODO: should any of these throw an exception instead of returning null?
JwtClaims claims = jwt.getClaims();
if (!config.getIssuer().equals(claims.getIssuer())) {
// issuer isn't us
return null;
}
if (!authorizationRequest.getClientId().equals(claims.getAudience())) {
// audience isn't the client
return null;
}
Date now = new Date();
if (!now.after(claims.getExpiration())) {
// token is expired
@ -164,14 +163,14 @@ public class JwtAssertionTokenGranter extends AbstractTokenGranter {
// we might need new calls on the token services layer to handle this, and we might
// need to handle id tokens separately.
return new OAuth2Authentication(authorizationRequest, null);
} else {
return null; // throw error??
}
*/
}
*/
}
}

View File

@ -43,11 +43,11 @@ import com.google.gson.JsonSerializer;
@Component("tokenIntrospection")
public class TokenIntrospectionView extends AbstractView {
private static Logger logger = LoggerFactory.getLogger(TokenIntrospectionView.class);
@Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) {
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) {
Gson gson = new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {
@ -68,7 +68,7 @@ public class TokenIntrospectionView extends AbstractView {
// serialize other classes without filter (lists and sets and things)
return false;
}
*/
*/
return false;
}
@ -84,28 +84,29 @@ public class TokenIntrospectionView extends AbstractView {
})
.registerTypeAdapter(OAuth2AccessTokenEntity.class, new JsonSerializer<OAuth2AccessTokenEntity>() {
public JsonElement serialize(OAuth2AccessTokenEntity src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject token = new JsonObject();
token.addProperty("valid", true);
JsonArray scopes = new JsonArray();
for (String scope : src.getScope()) {
scopes.add(new JsonPrimitive(scope));
}
token.add("scope", scopes);
token.add("expires_at", context.serialize(src.getExpiration()));
//token.addProperty("audience", src.getAuthenticationHolder().getAuthentication().getAuthorizationRequest().getClientId());
token.addProperty("subject", src.getAuthenticationHolder().getAuthentication().getName());
token.addProperty("client_id", src.getAuthenticationHolder().getAuthentication().getAuthorizationRequest().getClientId());
return token;
}
@Override
public JsonElement serialize(OAuth2AccessTokenEntity src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject token = new JsonObject();
token.addProperty("valid", true);
JsonArray scopes = new JsonArray();
for (String scope : src.getScope()) {
scopes.add(new JsonPrimitive(scope));
}
token.add("scope", scopes);
token.add("expires_at", context.serialize(src.getExpiration()));
//token.addProperty("audience", src.getAuthenticationHolder().getAuthentication().getAuthorizationRequest().getClientId());
token.addProperty("subject", src.getAuthenticationHolder().getAuthentication().getName());
token.addProperty("client_id", src.getAuthenticationHolder().getAuthentication().getAuthorizationRequest().getClientId());
return token;
}
})
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.create();
@ -113,9 +114,9 @@ public class TokenIntrospectionView extends AbstractView {
response.setContentType("application/json");
Writer out;
try {
out = response.getWriter();
Object obj = model.get("entity");
if (obj == null) {
@ -123,13 +124,13 @@ public class TokenIntrospectionView extends AbstractView {
}
gson.toJson(obj, out);
} catch (IOException e) {
logger.error("IOException occurred in TokenIntrospectionView.java: ", e);
}
}
}
}

View File

@ -16,7 +16,6 @@
package org.mitre.oauth2.web;
import java.security.Principal;
import java.util.HashMap;
import java.util.Map;
import org.mitre.oauth2.model.ClientDetailsEntity;
@ -28,14 +27,11 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
@ -45,53 +41,53 @@ public class IntrospectionEndpoint {
@Autowired
private OAuth2TokenEntityService tokenServices;
@Autowired
private ClientDetailsEntityService clientService;
private static Logger logger = LoggerFactory.getLogger(IntrospectionEndpoint.class);
public IntrospectionEndpoint() {
}
public IntrospectionEndpoint(OAuth2TokenEntityService tokenServices) {
this.tokenServices = tokenServices;
}
@PreAuthorize("hasRole('ROLE_CLIENT')")
@RequestMapping("/introspect")
public String verify(@RequestParam("token") String tokenValue, Principal p, Model model) {
if (Strings.isNullOrEmpty(tokenValue)) {
logger.error("Verify failed; token value is null");
Map<String,Boolean> entity = ImmutableMap.of("valid", Boolean.FALSE);
model.addAttribute("entity", entity);
return "jsonEntityView";
}
OAuth2AccessTokenEntity token = null;
try {
token = tokenServices.readAccessToken(tokenValue);
token = tokenServices.readAccessToken(tokenValue);
} catch (InvalidTokenException e) {
logger.error("Verify failed; AuthenticationException: " + e.getStackTrace().toString());
Map<String,Boolean> entity = ImmutableMap.of("valid", Boolean.FALSE);
model.addAttribute("entity", entity);
return "jsonEntityView";
}
ClientDetailsEntity tokenClient = token.getClient();
// clientID is the principal name in the authentication
String clientId = p.getName();
ClientDetailsEntity authClient = clientService.loadClientByClientId(clientId);
if (tokenClient != null && authClient != null) {
if (authClient.isAllowIntrospection()) {
// if it's the same client that the token was issued to, or it at least has all the scopes the token was issued with
if (authClient.equals(tokenClient) || authClient.getScope().containsAll(token.getScope())) {
// if it's a valid token, we'll print out information on it
model.addAttribute("entity", token);
return "tokenIntrospection";
@ -111,7 +107,7 @@ public class IntrospectionEndpoint {
model.addAttribute("code", HttpStatus.NOT_FOUND);
return "httpCodeView";
}
}
}

View File

@ -37,7 +37,6 @@ import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;
import com.google.common.collect.Sets;
@ -51,20 +50,20 @@ public class OAuthConfirmationController {
@Autowired
private ClientDetailsEntityService clientService;
@Autowired
private SystemScopeService scopeService;
private static Logger logger = LoggerFactory.getLogger(OAuthConfirmationController.class);
public OAuthConfirmationController() {
}
public OAuthConfirmationController(ClientDetailsEntityService clientService) {
this.clientService = clientService;
}
@PreAuthorize("hasRole('ROLE_USER')")
@RequestMapping("/oauth/confirm_access")
public String confimAccess(Map<String, Object> model, @ModelAttribute("authorizationRequest") AuthorizationRequest clientAuth) {
@ -77,14 +76,14 @@ public class OAuthConfirmationController {
model.put("code", HttpStatus.FORBIDDEN);
return "httpCodeView";
}
//AuthorizationRequest clientAuth = (AuthorizationRequest) model.remove("authorizationRequest");
ClientDetails client = null;
try {
client = clientService.loadClientByClientId(clientAuth.getClientId());
} catch (OAuth2Exception e) {
} catch (OAuth2Exception e) {
logger.error("confirmAccess: OAuth2Exception was thrown when attempting to load client: "
+ e.getStackTrace().toString());
model.put("code", HttpStatus.BAD_REQUEST);
@ -95,7 +94,7 @@ public class OAuthConfirmationController {
model.put("code", HttpStatus.BAD_REQUEST);
return "httpCodeView";
}
if (client == null) {
logger.error("confirmAccess: could not find client " + clientAuth.getClientId());
model.put("code", HttpStatus.NOT_FOUND);
@ -106,41 +105,41 @@ public class OAuthConfirmationController {
model.put("client", client);
String redirect_uri = clientAuth.getAuthorizationParameters().get("redirect_uri");
model.put("redirect_uri", redirect_uri);
Set<SystemScope> scopes = scopeService.fromStrings(clientAuth.getScope());
Set<SystemScope> sortedScopes = new LinkedHashSet<SystemScope>(scopes.size());
Set<SystemScope> systemScopes = scopeService.getAll();
// sort scopes for display
for (SystemScope s : systemScopes) {
if (scopes.contains(s)) {
sortedScopes.add(s);
}
}
sortedScopes.addAll(Sets.difference(scopes, systemScopes));
model.put("scopes", sortedScopes);
return "approve";
model.put("redirect_uri", redirect_uri);
Set<SystemScope> scopes = scopeService.fromStrings(clientAuth.getScope());
Set<SystemScope> sortedScopes = new LinkedHashSet<SystemScope>(scopes.size());
Set<SystemScope> systemScopes = scopeService.getAll();
// sort scopes for display
for (SystemScope s : systemScopes) {
if (scopes.contains(s)) {
sortedScopes.add(s);
}
}
sortedScopes.addAll(Sets.difference(scopes, systemScopes));
model.put("scopes", sortedScopes);
return "approve";
}
/**
* @return the clientService
*/
public ClientDetailsEntityService getClientService() {
return clientService;
}
* @return the clientService
*/
public ClientDetailsEntityService getClientService() {
return clientService;
}
/**
* @param clientService the clientService to set
*/
public void setClientService(ClientDetailsEntityService clientService) {
this.clientService = clientService;
}
* @param clientService the clientService to set
*/
public void setClientService(ClientDetailsEntityService clientService) {
this.clientService = clientService;
}
}

View File

@ -17,7 +17,6 @@ package org.mitre.oauth2.web;
import java.security.Principal;
import org.mitre.oauth2.exception.PermissionDeniedException;
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
import org.mitre.oauth2.model.OAuth2RefreshTokenEntity;
import org.mitre.oauth2.service.OAuth2TokenEntityService;
@ -26,7 +25,6 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.provider.AuthorizationRequest;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
@ -34,19 +32,18 @@ import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class RevocationEndpoint {
@Autowired
OAuth2TokenEntityService tokenServices;
private static Logger logger = LoggerFactory.getLogger(RevocationEndpoint.class);
public RevocationEndpoint() {
}
// TODO
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_CLIENT')")
@RequestMapping("/revoke")
@ -54,16 +51,16 @@ public class RevocationEndpoint {
// This is the token as passed in from OAuth (in case we need it some day)
//OAuth2AccessTokenEntity tok = tokenServices.getAccessToken((OAuth2Authentication) principal);
AuthorizationRequest clientAuth = null;
if (principal instanceof OAuth2Authentication) {
// if the client is acting on its own behalf (the common case), pull out the client authorization request
clientAuth = ((OAuth2Authentication) principal).getAuthorizationRequest();
}
try {
// check and handle access tokens first
OAuth2AccessTokenEntity accessToken = tokenServices.readAccessToken(tokenValue);
if (clientAuth != null) {
// client acting on its own, make sure it owns the token
@ -72,17 +69,17 @@ public class RevocationEndpoint {
model.addAttribute("code", HttpStatus.FORBIDDEN);
return "httpCodeView";
}
}
}
// if we got this far, we're allowed to do this
tokenServices.revokeAccessToken(accessToken);
model.addAttribute("code", HttpStatus.OK);
return "httpCodeView";
} catch (InvalidTokenException e) {
// access token wasn't found, check the refresh token
try {
OAuth2RefreshTokenEntity refreshToken = tokenServices.getRefreshToken(tokenValue);
if (clientAuth != null) {
@ -93,16 +90,16 @@ public class RevocationEndpoint {
return "httpCodeView";
}
}
// if we got this far, we're allowed to do this
tokenServices.revokeRefreshToken(refreshToken);
model.addAttribute("code", HttpStatus.OK);
return "httpCodeView";
} catch (InvalidTokenException e1) {
// neither token type was found, simply say "OK" and be on our way.
model.addAttribute("code", HttpStatus.OK);
return "httpCodeView";
}

View File

@ -5,9 +5,6 @@ package org.mitre.oauth2.web;
import java.util.Set;
import javax.persistence.EntityExistsException;
import javax.persistence.TransactionRequiredException;
import org.mitre.oauth2.model.SystemScope;
import org.mitre.oauth2.service.SystemScopeService;
import org.slf4j.Logger;
@ -35,35 +32,35 @@ public class ScopeAPI {
@Autowired
private SystemScopeService scopeService;
private static Logger logger = LoggerFactory.getLogger(ScopeAPI.class);
private Gson gson = new Gson();
@RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json")
public String getAll(ModelMap m) {
Set<SystemScope> allScopes = scopeService.getAll();
m.put("entity", allScopes);
return "jsonEntityView";
}
@RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = "application/json")
public String getScope(@PathVariable("id") Long id, ModelMap m) {
SystemScope scope = scopeService.getById(id);
if (scope != null) {
m.put("entity", scope);
return "jsonEntityView";
} else {
logger.error("getScope failed; scope not found: " + id);
m.put("code", HttpStatus.NOT_FOUND);
m.put("errorMessage", "The requested scope with id " + id + " could not be found.");
return "jsonErrorView";
@ -73,46 +70,46 @@ public class ScopeAPI {
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = "/{id}", method = RequestMethod.PUT, produces = "application/json", consumes = "application/json")
public String updateScope(@PathVariable("id") Long id, @RequestBody String json, ModelMap m) {
SystemScope existing = scopeService.getById(id);
SystemScope scope = gson.fromJson(json, SystemScope.class);
if (existing != null && scope != null) {
if (existing.getId().equals(scope.getId())) {
// sanity check
scope = scopeService.save(scope);
m.put("entity", scope);
return "jsonEntityView";
} else {
logger.error("updateScope failed; scope ids to not match: got "
logger.error("updateScope failed; scope ids to not match: got "
+ existing.getId() + " and " + scope.getId());
m.put("code", HttpStatus.BAD_REQUEST);
m.put("errorMessage", "Could not update scope. Scope ids to not match: got "
m.put("errorMessage", "Could not update scope. Scope ids to not match: got "
+ existing.getId() + " and " + scope.getId());
return "jsonErrorView";
}
} else {
logger.error("updateScope failed; scope with id " + id + " not found.");
m.put("code", HttpStatus.NOT_FOUND);
m.put("errorMessage", "Could not update scope. The scope with id " + id + " could not be found.");
return "jsonErrorView";
}
}
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = "", method = RequestMethod.POST, produces = "application/json", consumes = "application/json")
public String createScope(@RequestBody String json, ModelMap m) {
SystemScope scope = gson.fromJson(json, SystemScope.class);
SystemScope alreadyExists = scopeService.getByValue(scope.getValue());
if (alreadyExists != null) {
//Error, cannot save a scope with the same value as an existing one
@ -121,41 +118,41 @@ public class ScopeAPI {
m.put("errorMessage", "A scope with value " + scope.getValue() + " already exists, please choose a different value.");
return "jsonErrorView";
}
scope = scopeService.save(scope);
if (scope != null && scope.getId() != null) {
m.put("entity", scope);
return "jsonEntityView";
} else {
logger.error("createScope failed; JSON was invalid: " + json);
m.put("code", HttpStatus.BAD_REQUEST);
m.put("errorMessage", "Could not save new scope " + scope.getValue() + ". The scope service failed to return a saved entity.");
return "jsonErrorView";
}
}
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public String deleteScope(@PathVariable("id") Long id, ModelMap m) {
SystemScope existing = scopeService.getById(id);
if (existing != null) {
scopeService.remove(existing);
return "httpCodeView";
} else {
logger.error("deleteScope failed; scope with id " + id + " not found.");
m.put("code", HttpStatus.NOT_FOUND);
m.put("errorMessage", "Could not delete scope. The requested scope with id " + id + " could not be found.");
return "jsonErrorView";
}
}
}

View File

@ -38,10 +38,10 @@ import com.nimbusds.jwt.SignedJWT;
public class ConnectAuthorizationRequestManager implements AuthorizationRequestManager {
private static Logger logger = LoggerFactory.getLogger(ConnectAuthorizationRequestManager.class);
@Autowired
private NonceService nonceService;
@Autowired
private ClientDetailsEntityService clientDetailsService;
@ -58,32 +58,32 @@ public class ConnectAuthorizationRequestManager implements AuthorizationRequestM
this.clientDetailsService = clientDetailsService;
this.nonceService = nonceService;
}
/**
* Default empty constructor
*/
public ConnectAuthorizationRequestManager() {
}
@Override
public AuthorizationRequest createAuthorizationRequest(Map<String, String> inputParams) {
Map<String, String> parameters = processRequestObject(inputParams);
String clientId = parameters.get("client_id");
if (clientId == null) {
throw new InvalidClientException("A client id must be provided");
}
ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
String requestNonce = parameters.get("nonce");
//Only process if the user is authenticated. If the user is not authenticated yet, this
//code will be called a second time once the user is redirected from the login page back
//Only process if the user is authenticated. If the user is not authenticated yet, this
//code will be called a second time once the user is redirected from the login page back
//to the auth endpoint.
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (requestNonce != null && principal != null && principal instanceof User) {
if (!nonceService.alreadyUsed(clientId, requestNonce)) {
@ -93,17 +93,17 @@ public class ConnectAuthorizationRequestManager implements AuthorizationRequestM
else {
throw new NonceReuseException(client.getClientId(), requestNonce);
}
}
Set<String> scopes = OAuth2Utils.parseParameterList(parameters.get("scope"));
if ((scopes == null || scopes.isEmpty())) {
//TODO: do we want to allow default scoping at all?
Set<String> clientScopes = client.getScope();
scopes = clientScopes;
}
// note that we have to inject the processed parameters in at this point so that SECOAUTH can find them later (and this object will get copy-constructored away anyway)
DefaultAuthorizationRequest request = new DefaultAuthorizationRequest(parameters, Collections.<String, String> emptyMap(), clientId, scopes);
request.addClientDetails(client);
@ -115,46 +115,46 @@ public class ConnectAuthorizationRequestManager implements AuthorizationRequestM
* @param inputParams
* @return
*/
private Map<String, String> processRequestObject(Map<String, String> inputParams) {
String jwtString = inputParams.get("request");
// if there's no request object, bail early
if (Strings.isNullOrEmpty(jwtString)) {
return inputParams;
}
private Map<String, String> processRequestObject(Map<String, String> inputParams) {
// start by copying over what's already in there
Map<String, String> parameters = new HashMap<String, String>(inputParams);
String jwtString = inputParams.get("request");
// if there's no request object, bail early
if (Strings.isNullOrEmpty(jwtString)) {
return inputParams;
}
// start by copying over what's already in there
Map<String, String> parameters = new HashMap<String, String>(inputParams);
// parse the request object
try {
SignedJWT jwsObject = SignedJWT.parse(jwtString);
JSONObject claims = jwsObject.getPayload().toJSONObject();
// parse the request object
try {
SignedJWT jwsObject = SignedJWT.parse(jwtString);
JSONObject claims = jwsObject.getPayload().toJSONObject();
// TODO: check parameter consistency, move keys to constants
String clientId = JSONObjectUtils.getString(claims, "client_id");
if (clientId != null) {
parameters.put("client_id", clientId);
}
ClientDetailsEntity client = clientDetailsService.loadClientByClientId(clientId);
if (client.getJwksUri() == null) {
throw new InvalidClientException("Client must have a JWKS URI registered to use request objects.");
}
// check JWT signature
JwtSigningAndValidationService validator = validators.get(client.getJwksUri());
if (validator == null) {
throw new InvalidClientException("Unable to create signature validator for client's JWKS URI: " + client.getJwksUri());
}
if (!validator.validateSignature(jwsObject)) {
throw new AuthenticationServiceException("Signature did not validate for presented JWT request object.");
}
/*
* if (in Claims):
* if (in params):
@ -167,59 +167,59 @@ public class ConnectAuthorizationRequestManager implements AuthorizationRequestM
* else (not in claims):
* we don't care
*/
String responseTypes = JSONObjectUtils.getString(claims, "response_type");
if (responseTypes != null) {
parameters.put("response_type", responseTypes);
}
if (claims.get("redirect_uri") != null) {
if (inputParams.containsKey("redirect_uri") == false) {
parameters.put("redirect_uri", JSONObjectUtils.getString(claims, "redirect_uri"));
}
}
String state = JSONObjectUtils.getString(claims, "state");
if(state != null) {
if (inputParams.containsKey("state") == false) {
parameters.put("state", state);
}
}
String nonce = JSONObjectUtils.getString(claims, "nonce");
if(nonce != null) {
if (inputParams.containsKey("nonce") == false) {
parameters.put("nonce", nonce);
}
}
String display = JSONObjectUtils.getString(claims, "display");
if (display != null) {
if (inputParams.containsKey("display") == false) {
parameters.put("display", display);
}
}
String prompt = JSONObjectUtils.getString(claims, "prompt");
if (prompt != null) {
if (inputParams.containsKey("prompt") == false) {
parameters.put("prompt", prompt);
}
}
String scope = JSONObjectUtils.getString(claims, "scope");
if (scope != null) {
if (inputParams.containsKey("scope") == false) {
parameters.put("scope", scope);
}
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return parameters;
}
}
@Override
public void validateParameters(Map<String, String> parameters, ClientDetails clientDetails) {

View File

@ -18,19 +18,19 @@ public class JwtBearerAssertionAuthenticationToken extends AbstractAuthenticatio
private String clientId;
private JWT jwt;
/**
* Create an unauthenticated token with the given client ID and jwt
* @param clientId
* @param jwt
*/
public JwtBearerAssertionAuthenticationToken(String clientId, JWT jwt) {
super(null);
this.clientId = clientId;
this.jwt = jwt;
setAuthenticated(false);
}
super(null);
this.clientId = clientId;
this.jwt = jwt;
setAuthenticated(false);
}
/**
* Create an authenticated token with the given clientID, jwt, and authorities set
* @param clientId
@ -38,11 +38,11 @@ public class JwtBearerAssertionAuthenticationToken extends AbstractAuthenticatio
* @param authorities
*/
public JwtBearerAssertionAuthenticationToken(String clientId, JWT jwt, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.clientId = clientId;
this.jwt = jwt;
setAuthenticated(true);
}
super(authorities);
this.clientId = clientId;
this.jwt = jwt;
setAuthenticated(true);
}
/* (non-Javadoc)
* @see org.springframework.security.core.Authentication#getCredentials()
@ -61,42 +61,42 @@ public class JwtBearerAssertionAuthenticationToken extends AbstractAuthenticatio
}
/**
* @return the clientId
*/
public String getClientId() {
return clientId;
}
* @return the clientId
*/
public String getClientId() {
return clientId;
}
/**
* @param clientId the clientId to set
*/
public void setClientId(String clientId) {
this.clientId = clientId;
}
* @param clientId the clientId to set
*/
public void setClientId(String clientId) {
this.clientId = clientId;
}
/**
* @return the jwt
*/
public JWT getJwt() {
return jwt;
}
* @return the jwt
*/
public JWT getJwt() {
return jwt;
}
/**
* @param jwt the jwt to set
*/
public void setJwt(JWT jwt) {
this.jwt = jwt;
}
* @param jwt the jwt to set
*/
public void setJwt(JWT jwt) {
this.jwt = jwt;
}
/**
* Clear out the JWT that this token holds.
*/
@Override
public void eraseCredentials() {
super.eraseCredentials();
setJwt(null);
}
*/
@Override
public void eraseCredentials() {
super.eraseCredentials();
setJwt(null);
}
}

View File

@ -36,49 +36,49 @@ public class JwtBearerAuthenticationProvider implements AuthenticationProvider {
// map of verifiers, load keys for clients
@Autowired
private JWKSetSigningAndValidationServiceCacheService validators;
// Allow for time sync issues by having a window of X seconds.
private int timeSkewAllowance = 300;
// to load clients
@Autowired
private ClientDetailsEntityService clientService;
// to get our server's issuer url
@Autowired
private ConfigurationPropertiesBean config;
/**
* Try to validate the client credentials by parsing and validating the JWT.
*/
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
JwtBearerAssertionAuthenticationToken jwtAuth = (JwtBearerAssertionAuthenticationToken)authentication;
try {
ClientDetailsEntity client = clientService.loadClientByClientId(jwtAuth.getClientId());
*/
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
JWT jwt = jwtAuth.getJwt();
ReadOnlyJWTClaimsSet jwtClaims = jwt.getJWTClaimsSet();
JwtBearerAssertionAuthenticationToken jwtAuth = (JwtBearerAssertionAuthenticationToken)authentication;
try {
ClientDetailsEntity client = clientService.loadClientByClientId(jwtAuth.getClientId());
JWT jwt = jwtAuth.getJwt();
ReadOnlyJWTClaimsSet jwtClaims = jwt.getJWTClaimsSet();
// check the signature with nimbus
if (jwt instanceof SignedJWT) {
SignedJWT jws = (SignedJWT)jwt;
JwtSigningAndValidationService validator = validators.get(client.getJwksUri());
if (validator == null || !validator.validateSignature(jws)) {
throw new AuthenticationServiceException("Invalid signature");
}
}
// check the signature with nimbus
if (jwt instanceof SignedJWT) {
SignedJWT jws = (SignedJWT)jwt;
JwtSigningAndValidationService validator = validators.get(client.getJwksUri());
if (validator == null || !validator.validateSignature(jws)) {
throw new AuthenticationServiceException("Invalid signature");
}
}
// check the issuer
if (jwtClaims.getIssuer() == null) {
throw new AuthenticationServiceException("Assertion Token Issuer is null");
} else if (!jwtClaims.getIssuer().equals(client.getClientId())){
throw new AuthenticationServiceException("Issuers do not match, expected " + client.getClientId() + " got " + jwtClaims.getIssuer());
}
// check expiration
if (jwtClaims.getExpirationTime() == null) {
throw new AuthenticationServiceException("Assertion Token does not have required expiration claim");
@ -89,7 +89,7 @@ public class JwtBearerAuthenticationProvider implements AuthenticationProvider {
throw new AuthenticationServiceException("Assertion Token is expired: " + jwtClaims.getExpirationTime());
}
}
// check not before
if (jwtClaims.getNotBeforeTime() != null) {
Date now = new Date(System.currentTimeMillis() + (timeSkewAllowance * 1000));
@ -97,7 +97,7 @@ public class JwtBearerAuthenticationProvider implements AuthenticationProvider {
throw new AuthenticationServiceException("Assertion Token not valid untill: " + jwtClaims.getNotBeforeTime());
}
}
// check issued at
if (jwtClaims.getIssueTime() != null) {
// since it's not null, see if it was issued in the future
@ -106,32 +106,32 @@ public class JwtBearerAuthenticationProvider implements AuthenticationProvider {
throw new AuthenticationServiceException("Assertion Token was issued in the future: " + jwtClaims.getIssueTime());
}
}
// check audience
if (jwtClaims.getAudience() == null) {
throw new AuthenticationServiceException("Assertion token audience is null");
throw new AuthenticationServiceException("Assertion token audience is null");
} else if (!jwtClaims.getAudience().contains(config.getIssuer())) {
throw new AuthenticationServiceException("Audience does not match, expected " + config.getIssuer() + " got " + jwtClaims.getAudience());
}
// IFF we managed to get all the way down here, the token is valid
// IFF we managed to get all the way down here, the token is valid
return new JwtBearerAssertionAuthenticationToken(client.getClientId(), jwt, client.getAuthorities());
} catch (InvalidClientException e) {
throw new UsernameNotFoundException("Could not find client: " + jwtAuth.getClientId());
} catch (ParseException e) {
// TODO Auto-generated catch block
throw new AuthenticationServiceException("Invalid JWT format");
}
}
} catch (InvalidClientException e) {
throw new UsernameNotFoundException("Could not find client: " + jwtAuth.getClientId());
} catch (ParseException e) {
// TODO Auto-generated catch block
throw new AuthenticationServiceException("Invalid JWT format");
}
}
/**
* We support {@link JwtBearerAssertionAuthenticationToken}s only.
*/
@Override
public boolean supports(Class<?> authentication) {
return (JwtBearerAssertionAuthenticationToken.class.isAssignableFrom(authentication));
}
*/
@Override
public boolean supports(Class<?> authentication) {
return (JwtBearerAssertionAuthenticationToken.class.isAssignableFrom(authentication));
}
}

View File

@ -28,74 +28,74 @@ import com.nimbusds.jwt.JWTParser;
public class JwtBearerClientAssertionTokenEndpointFilter extends ClientCredentialsTokenEndpointFilter {
public JwtBearerClientAssertionTokenEndpointFilter() {
super();
// TODO Auto-generated constructor stub
}
super();
// TODO Auto-generated constructor stub
}
public JwtBearerClientAssertionTokenEndpointFilter(String path) {
super(path);
// TODO Auto-generated constructor stub
}
super(path);
// TODO Auto-generated constructor stub
}
/**
* Pull the assertion out of the request and send it up to the auth manager for processing.
*/
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
*/
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
// check for appropriate parameters
String assertionType = request.getParameter("client_assertion_type");
String assertion = request.getParameter("client_assertion");
try {
JWT jwt = JWTParser.parse(assertion);
String clientId = jwt.getJWTClaimsSet().getSubject();
Authentication authRequest = new JwtBearerAssertionAuthenticationToken(clientId, jwt);
return this.getAuthenticationManager().authenticate(authRequest);
} catch (ParseException e) {
throw new BadCredentialsException("Invalid JWT credential: " + assertion);
}
}
// check for appropriate parameters
String assertionType = request.getParameter("client_assertion_type");
String assertion = request.getParameter("client_assertion");
try {
JWT jwt = JWTParser.parse(assertion);
String clientId = jwt.getJWTClaimsSet().getSubject();
Authentication authRequest = new JwtBearerAssertionAuthenticationToken(clientId, jwt);
return this.getAuthenticationManager().authenticate(authRequest);
} catch (ParseException e) {
throw new BadCredentialsException("Invalid JWT credential: " + assertion);
}
}
/**
* Check to see if the "client_assertion_type" and "client_assertion" parameters are present and contain the right values.
*/
@Override
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
// check for appropriate parameters
String assertionType = request.getParameter("client_assertion_type");
String assertion = request.getParameter("client_assertion");
*/
@Override
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
// check for appropriate parameters
String assertionType = request.getParameter("client_assertion_type");
String assertion = request.getParameter("client_assertion");
if (Strings.isNullOrEmpty(assertionType) || Strings.isNullOrEmpty(assertion)) {
return false;
} else if (!assertionType.equals("urn:ietf:params:oauth:client-assertion-type:jwt-bearer")) {
return false;
}
// Can't call to superclass here b/c client creds would break for lack of client_id
// return super.requiresAuthentication(request, response);
String uri = request.getRequestURI();
int pathParamIndex = uri.indexOf(';');
if (pathParamIndex > 0) {
// strip everything after the first semi-colon
uri = uri.substring(0, pathParamIndex);
}
if ("".equals(request.getContextPath())) {
return uri.endsWith(getFilterProcessesUrl());
}
return uri.endsWith(request.getContextPath() + getFilterProcessesUrl());
}
if (Strings.isNullOrEmpty(assertionType) || Strings.isNullOrEmpty(assertion)) {
return false;
} else if (!assertionType.equals("urn:ietf:params:oauth:client-assertion-type:jwt-bearer")) {
return false;
}
// Can't call to superclass here b/c client creds would break for lack of client_id
// return super.requiresAuthentication(request, response);
String uri = request.getRequestURI();
int pathParamIndex = uri.indexOf(';');
if (pathParamIndex > 0) {
// strip everything after the first semi-colon
uri = uri.substring(0, pathParamIndex);
}
if ("".equals(request.getContextPath())) {
return uri.endsWith(getFilterProcessesUrl());
}
return uri.endsWith(request.getContextPath() + getFilterProcessesUrl());
}
}

View File

@ -11,14 +11,11 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;
@ -30,7 +27,7 @@ import com.google.common.base.Strings;
*/
@Component("promptFilter")
public class PromptFilter extends GenericFilterBean {
private Logger logger = LoggerFactory.getLogger(PromptFilter.class);
/**
@ -38,33 +35,33 @@ public class PromptFilter extends GenericFilterBean {
*/
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (!Strings.isNullOrEmpty(request.getParameter("prompt"))) {
// we have a "prompt" parameter
if (request.getParameter("prompt").equals("none")) {
logger.info("Client requested no prompt");
// see if the user's logged in
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
// user's been logged in already (by session management)
// we're OK, continue without prompting
chain.doFilter(req, res);
} else {
// user hasn't been logged in, we need to "return an error"
logger.info("User not logged in, no prompt requested, returning 403 from filter");
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
return;
}
/* TODO: this is an attempt to catch the prompt=login case, but it results in an infinite loop so it's commented out
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (!Strings.isNullOrEmpty(request.getParameter("prompt"))) {
// we have a "prompt" parameter
if (request.getParameter("prompt").equals("none")) {
logger.info("Client requested no prompt");
// see if the user's logged in
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
// user's been logged in already (by session management)
// we're OK, continue without prompting
chain.doFilter(req, res);
} else {
// user hasn't been logged in, we need to "return an error"
logger.info("User not logged in, no prompt requested, returning 403 from filter");
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
return;
}
/* TODO: this is an attempt to catch the prompt=login case, but it results in an infinite loop so it's commented out
} else if (request.getParameter("prompt").equals("login")) {
// see if the user's logged in
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
// user's been logged in already (by session management)
// log them out and continue
@ -74,17 +71,17 @@ public class PromptFilter extends GenericFilterBean {
// user hasn't been logged in yet, we can keep going
chain.doFilter(req, res);
}
*/
} else {
// prompt parameter is a value we don't care about, not our business
chain.doFilter(req, res);
}
} else {
// no prompt parameter, not our business
chain.doFilter(req, res);
}
*/
} else {
// prompt parameter is a value we don't care about, not our business
chain.doFilter(req, res);
}
} else {
// no prompt parameter, not our business
chain.doFilter(req, res);
}
}
}

View File

@ -15,8 +15,6 @@
******************************************************************************/
package org.mitre.openid.connect.repository.impl;
import static org.mitre.util.jpa.JpaUtil.saveOrUpdate;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@ -25,6 +23,8 @@ import org.mitre.openid.connect.repository.AddressRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import static org.mitre.util.jpa.JpaUtil.saveOrUpdate;
/**
* JPA Address repository implementation
*

View File

@ -15,8 +15,6 @@
******************************************************************************/
package org.mitre.openid.connect.repository.impl;
import static org.mitre.util.jpa.JpaUtil.saveOrUpdate;
import java.util.Collection;
import javax.persistence.EntityManager;
@ -25,10 +23,11 @@ import javax.persistence.TypedQuery;
import org.mitre.openid.connect.model.ApprovedSite;
import org.mitre.openid.connect.repository.ApprovedSiteRepository;
import org.mitre.util.jpa.JpaUtil;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import static org.mitre.util.jpa.JpaUtil.saveOrUpdate;
/**
* JPA ApprovedSite repository implementation
*
@ -48,7 +47,7 @@ public class JpaApprovedSiteRepository implements ApprovedSiteRepository {
"ApprovedSite.getAll", ApprovedSite.class);
return query.getResultList();
}
@Override
@Transactional
public ApprovedSite getById(Long id) {
@ -59,7 +58,7 @@ public class JpaApprovedSiteRepository implements ApprovedSiteRepository {
@Transactional
public void remove(ApprovedSite approvedSite) {
ApprovedSite found = manager.find(ApprovedSite.class, approvedSite.getId());
if (found != null) {
manager.remove(found);
} else {
@ -75,30 +74,30 @@ public class JpaApprovedSiteRepository implements ApprovedSiteRepository {
@Override
public Collection<ApprovedSite> getByClientIdAndUserId(String clientId, String userId) {
TypedQuery<ApprovedSite> query = manager.createNamedQuery("ApprovedSite.getByClientIdAndUserId", ApprovedSite.class);
query.setParameter("userId", userId);
query.setParameter("clientId", clientId);
return query.getResultList();
}
@Override
@Transactional
public Collection<ApprovedSite> getByUserId(String userId) {
@Override
@Transactional
public Collection<ApprovedSite> getByUserId(String userId) {
TypedQuery<ApprovedSite> query = manager.createNamedQuery("ApprovedSite.getByUserId", ApprovedSite.class);
query.setParameter("userId", userId);
return query.getResultList();
}
@Override
@Transactional
public Collection<ApprovedSite> getByClientId(String clientId) {
}
@Override
@Transactional
public Collection<ApprovedSite> getByClientId(String clientId) {
TypedQuery<ApprovedSite> query = manager.createNamedQuery("ApprovedSite.getByClientId", ApprovedSite.class);
query.setParameter("clientId", clientId);
return query.getResultList();
}
}
}

Some files were not shown because too many files have changed in this diff Show More