/*
* oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
*
* Copyright (c) 2014, Gluu
*/
package org.xdi.oxauth.model.common;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xdi.oxauth.model.authorize.JwtAuthorizationRequest;
import org.xdi.oxauth.model.authorize.ScopeChecker;
import org.xdi.oxauth.model.configuration.AppConfiguration;
import org.xdi.oxauth.model.ldap.TokenLdap;
import org.xdi.oxauth.model.registration.Client;
import org.xdi.oxauth.util.TokenHashUtil;
import javax.inject.Inject;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* @author Yuriy Zabrovarnyy
* @author Javier Rojas Blum
* @author Yuriy Movchan
* @version November 11, 2016
*/
public abstract class AbstractAuthorizationGrant implements IAuthorizationGrant {
private static final Logger log = LoggerFactory.getLogger(AbstractAuthorizationGrant.class);
@Inject
protected AppConfiguration appConfiguration;
@Inject
protected ScopeChecker scopeChecker;
private User user;
private AuthorizationGrantType authorizationGrantType;
private Client client;
private Set<String> scopes;
private String grantId;
private JwtAuthorizationRequest jwtAuthorizationRequest;
private Date authenticationTime;
private TokenLdap tokenLdap;
private AccessToken longLivedAccessToken;
private IdToken idToken;
private AuthorizationCode authorizationCode;
private String nonce;
private String codeChallenge;
private String codeChallengeMethod;
private String acrValues;
private String sessionDn;
protected final ConcurrentMap<String, AccessToken> accessTokens = new ConcurrentHashMap<String, AccessToken>();
protected final ConcurrentMap<String, RefreshToken> refreshTokens = new ConcurrentHashMap<String, RefreshToken>();
public AbstractAuthorizationGrant() {}
protected AbstractAuthorizationGrant(User user, AuthorizationGrantType authorizationGrantType, Client client,
Date authenticationTime) {
init(user, authorizationGrantType, client, authenticationTime);
}
protected void init(User user, AuthorizationGrantType authorizationGrantType, Client client,
Date authenticationTime) {
this.authenticationTime = authenticationTime != null ? new Date(authenticationTime.getTime()) : null;
this.user = user;
this.authorizationGrantType = authorizationGrantType;
this.client = client;
this.scopes = new CopyOnWriteArraySet<String>();
this.grantId = UUID.randomUUID().toString();
}
@Override
public synchronized String getGrantId() {
return grantId;
}
@Override
public synchronized void setGrantId(String p_grantId) {
grantId = p_grantId;
}
/**
* Returns the {@link AuthorizationCode}.
*
* @return The authorization code.
*/
@Override
public AuthorizationCode getAuthorizationCode() {
return authorizationCode;
}
/**
* Sets the {@link AuthorizationCode}.
*
* @param authorizationCode
* The authorization code.
*/
@Override
public void setAuthorizationCode(AuthorizationCode authorizationCode) {
this.authorizationCode = authorizationCode;
}
@Override
public String getNonce() {
return nonce;
}
@Override
public void setNonce(String nonce) {
this.nonce = nonce;
}
public String getCodeChallenge() {
return codeChallenge;
}
public void setCodeChallenge(String codeChallenge) {
this.codeChallenge = codeChallenge;
}
public String getCodeChallengeMethod() {
return codeChallengeMethod;
}
public void setCodeChallengeMethod(String codeChallengeMethod) {
this.codeChallengeMethod = codeChallengeMethod;
}
/**
* Returns a list with all the issued refresh tokens codes.
*
* @return List with all the issued refresh tokens codes.
*/
@Override
public Set<String> getRefreshTokensCodes() {
return refreshTokens.keySet();
}
/**
* Returns a list with all the issued access tokens codes.
*
* @return List with all the issued access tokens codes.
*/
@Override
public Set<String> getAccessTokensCodes() {
return accessTokens.keySet();
}
/**
* Returns a list with all the issued access tokens.
*
* @return List with all the issued access tokens.
*/
@Override
public List<AccessToken> getAccessTokens() {
return new ArrayList<AccessToken>(accessTokens.values());
}
@Override
public void setScopes(Collection<String> scopes) {
this.scopes.clear();
this.scopes.addAll(scopes);
}
@Override
public AccessToken getLongLivedAccessToken() {
return longLivedAccessToken;
}
@Override
public void setLongLivedAccessToken(AccessToken longLivedAccessToken) {
this.longLivedAccessToken = longLivedAccessToken;
}
@Override
public IdToken getIdToken() {
return idToken;
}
@Override
public void setIdToken(IdToken idToken) {
this.idToken = idToken;
}
@Override
public TokenLdap getTokenLdap() {
return tokenLdap;
}
@Override
public void setTokenLdap(TokenLdap p_tokenLdap) {
this.tokenLdap = p_tokenLdap;
}
/**
* Returns the resource owner's.
*
* @return The resource owner's.
*/
@Override
public User getUser() {
return user;
}
public String getAcrValues() {
return acrValues;
}
public void setAcrValues(String acrValues) {
this.acrValues = acrValues;
}
public String getSessionDn() {
return sessionDn;
}
public void setSessionDn(String sessionDn) {
this.sessionDn = sessionDn;
}
/**
* Checks the scopes policy configured according to the type of the
* authorization grant to limit the issued token scopes.
*
* @param requestedScopes
* A space-delimited list of values in which the order of values
* does not matter.
* @return A space-delimited list of scopes
*/
@Override
public String checkScopesPolicy(String requestedScopes) {
this.scopes.clear();
Set<String> grantedScopes = scopeChecker.checkScopesPolicy(client, requestedScopes);
this.scopes.addAll(grantedScopes);
final StringBuilder grantedScopesSb = new StringBuilder();
for (String scope : scopes) {
grantedScopesSb.append(" ").append(scope);
}
final String grantedScopesSt = grantedScopesSb.toString().trim();
return grantedScopesSt;
}
@Override
public AccessToken createAccessToken() {
int lifetime = appConfiguration.getShortLivedAccessTokenLifetime();
AccessToken accessToken = new AccessToken(lifetime);
accessToken.setAuthMode(getAcrValues());
accessToken.setSessionDn(getSessionDn());
return accessToken;
}
@Override
public AccessToken createLongLivedAccessToken() {
int lifetime = appConfiguration.getLongLivedAccessTokenLifetime();
AccessToken accessToken = new AccessToken(lifetime);
accessToken.setAuthMode(getAcrValues());
accessToken.setSessionDn(getSessionDn());
return accessToken;
}
@Override
public RefreshToken createRefreshToken() {
int lifetime = appConfiguration.getRefreshTokenLifetime();
RefreshToken refreshToken = new RefreshToken(lifetime);
refreshToken.setAuthMode(getAcrValues());
refreshToken.setSessionDn(getSessionDn());
return refreshToken;
}
@Override
public String getUserId() {
if (user == null) {
return null;
}
return user.getUserId();
}
@Override
public String getUserDn() {
if (user == null) {
return null;
}
return user.getDn();
}
/**
* Returns the {@link AuthorizationGrantType}.
*
* @return The authorization grant type.
*/
@Override
public AuthorizationGrantType getAuthorizationGrantType() {
return authorizationGrantType;
}
/**
* Returns the {@link org.xdi.oxauth.model.registration.Client}. An
* application making protected resource requests on behalf of the resource
* owner and with its authorization.
*
* @return The client.
*/
@Override
public Client getClient() {
return client;
}
@Override
public String getClientId() {
if (client == null) {
return null;
}
return client.getClientId();
}
@Override
public String getClientDn() {
if (client == null) {
return null;
}
return client.getDn();
}
@Override
public Date getAuthenticationTime() {
return authenticationTime;
}
public void setAuthenticationTime(Date authenticationTime) {
this.authenticationTime = authenticationTime;
}
/**
* Returns a list of the scopes granted to the client.
*
* @return List of the scopes granted to the client.
*/
@Override
public Set<String> getScopes() {
return scopes;
}
@Override
public JwtAuthorizationRequest getJwtAuthorizationRequest() {
return jwtAuthorizationRequest;
}
@Override
public void setJwtAuthorizationRequest(JwtAuthorizationRequest p_jwtAuthorizationRequest) {
jwtAuthorizationRequest = p_jwtAuthorizationRequest;
}
@Override
public void setAccessTokens(List<AccessToken> accessTokens) {
put(this.accessTokens, accessTokens);
}
private static <T extends AbstractToken> void put(ConcurrentMap<String, T> p_map, List<T> p_list) {
p_map.clear();
if (p_list != null && !p_list.isEmpty()) {
for (T t : p_list) {
p_map.put(t.getCode(), t);
}
}
}
/**
* Returns a list with all the issued refresh tokens.
*
* @return List with all the issued refresh tokens.
*/
@Override
public List<RefreshToken> getRefreshTokens() {
return new ArrayList<RefreshToken>(refreshTokens.values());
}
@Override
public void setRefreshTokens(List<RefreshToken> refreshTokens) {
put(this.refreshTokens, refreshTokens);
}
/**
* Gets the refresh token instance from the refresh token list given its
* code.
*
* @param refreshTokenCode
* The code of the refresh token.
* @return The refresh token instance or <code>null</code> if not found.
*/
@Override
public RefreshToken getRefreshToken(String refreshTokenCode) {
if (log.isTraceEnabled()) {
log.trace("Looking for the refresh token: " + refreshTokenCode + " for an authorization grant of type: "
+ getAuthorizationGrantType());
}
return refreshTokens.get(refreshTokenCode);
}
/**
* Gets the access token instance from the id token list or the access token
* list given its code.
*
* @param tokenCode
* The code of the access token.
* @return The access token instance or <code>null</code> if not found.
*/
@Override
public AbstractToken getAccessToken(String tokenCode) {
String hashedTokenCode = TokenHashUtil.getHashedToken(tokenCode);
final IdToken idToken = getIdToken();
if (idToken != null) {
if (idToken.getCode().equals(hashedTokenCode)) {
return idToken;
}
}
final AccessToken longLivedAccessToken = getLongLivedAccessToken();
if (longLivedAccessToken != null) {
if (longLivedAccessToken.getCode().equals(hashedTokenCode)) {
return longLivedAccessToken;
}
}
return accessTokens.get(hashedTokenCode);
}
@Override
public String toString() {
return "AbstractAuthorizationGrant{" + "user=" + user + ", authorizationCode=" + authorizationCode + ", client="
+ client + ", grantId='" + grantId + '\'' + ", nonce='" + nonce + '\'' + ", acrValues='" + acrValues
+ '\'' + ", sessionDn='" + sessionDn + '\'' + ", codeChallenge='" + codeChallenge + '\''
+ ", codeChallengeMethod='" + codeChallengeMethod + '\'' + ", authenticationTime=" + authenticationTime
+ ", scopes=" + scopes + ", authorizationGrantType=" + authorizationGrantType + '}';
}
}