diff options
Diffstat (limited to 'plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2DataProvider.java')
-rw-r--r-- | plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2DataProvider.java | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2DataProvider.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2DataProvider.java new file mode 100644 index 00000000000..40fdf644e3d --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2DataProvider.java @@ -0,0 +1,313 @@ +/******************************************************************************* + * Copyright (c) 2014 Boeing. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Boeing - initial API and implementation + *******************************************************************************/ +package org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider; + +import java.util.Collections; +import java.util.List; +import javax.crypto.SecretKey; +import org.apache.cxf.rs.security.oauth2.common.AccessTokenRegistration; +import org.apache.cxf.rs.security.oauth2.common.Client; +import org.apache.cxf.rs.security.oauth2.common.OAuthError; +import org.apache.cxf.rs.security.oauth2.common.OAuthPermission; +import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken; +import org.apache.cxf.rs.security.oauth2.common.UserSubject; +import org.apache.cxf.rs.security.oauth2.grants.code.AuthorizationCodeDataProvider; +import org.apache.cxf.rs.security.oauth2.grants.code.AuthorizationCodeRegistration; +import org.apache.cxf.rs.security.oauth2.grants.code.ServerAuthorizationCodeGrant; +import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException; +import org.apache.cxf.rs.security.oauth2.tokens.refresh.RefreshToken; +import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; +import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils; +import org.eclipse.osee.framework.jdk.core.util.Lib; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.adapters.AccessToken; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.adapters.AuthorizationCode; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.adapters.OAuthEncryption; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.adapters.RefreshOAuthToken; +import org.eclipse.osee.jaxrs.server.security.JaxRsOAuthStorage; +import org.eclipse.osee.jaxrs.server.security.OAuthCodeGrant; +import org.eclipse.osee.jaxrs.server.security.OAuthToken; +import org.eclipse.osee.jaxrs.server.security.OAuthTokenType; + +/** + * @author Roberto E. Escobar + */ +public class OAuth2DataProvider implements AuthorizationCodeDataProvider { + + private final OAuthEncryption serializer; + private final JaxRsOAuthStorage storage; + private final ClientProvider clientProvider; + private final SubjectProvider subjectProvider; + + private boolean isRefreshTokenAllowed; + private long accessTokenExpiration; + private long refreshTokenExpiration; + private long codeGrantExpiration; + + private String secretKeyEncoded; + private String secretKeyAlgorithm; + + private volatile SecretKey secretKey; + + public OAuth2DataProvider(ClientProvider clientProvider, SubjectProvider subjectProvider, OAuthEncryption serializer, JaxRsOAuthStorage storage) { + super(); + this.clientProvider = clientProvider; + this.subjectProvider = subjectProvider; + this.serializer = serializer; + this.storage = storage; + } + + public void setSecretKeyEncoded(String secretKeyEncoded) { + this.secretKeyEncoded = secretKeyEncoded; + } + + public void setSecretKeyAlgorithm(String secretKeyAlgorithm) { + this.secretKeyAlgorithm = secretKeyAlgorithm; + } + + public void setRefreshTokenAllowed(boolean isRefreshTokenAllowed) { + this.isRefreshTokenAllowed = isRefreshTokenAllowed; + } + + public void setAccessTokenExpiration(long accessTokenExpiration) { + this.accessTokenExpiration = accessTokenExpiration; + } + + public void setRefreshTokenExpiration(long refreshTokenExpiration) { + this.refreshTokenExpiration = refreshTokenExpiration; + } + + public void setCodeGrantExpiration(long codeGrantExpiration) { + this.codeGrantExpiration = codeGrantExpiration; + } + + public boolean isRefreshTokenAllowed() { + return isRefreshTokenAllowed; + } + + public long getAccessTokenExpiration() { + return accessTokenExpiration; + } + + public long getRefreshTokenExpiration() { + return refreshTokenExpiration; + } + + public long getCodeGrantExpiration() { + return codeGrantExpiration; + } + + private SecretKey getSecretKey() { + if (secretKey == null) { + secretKey = serializer.decodeSecretKey(secretKeyEncoded, secretKeyAlgorithm); + } + return secretKey; + } + + private long getClientId(Client client) { + return clientProvider.getClientId(client); + } + + private long getSubjectId(UserSubject subject) { + return subjectProvider.getSubjectId(subject); + } + + @Override + public Client getClient(String clientId) { + return clientProvider.getClient(clientId); + } + + @Override + public ServerAuthorizationCodeGrant createCodeGrant(AuthorizationCodeRegistration reg) { + long expiresIn = getCodeGrantExpiration(); + + long uuid = Lib.generateUuid(); + long clientId = getClientId(reg.getClient()); + long subjectId = getSubjectId(reg.getSubject()); + + AuthorizationCode grant = new AuthorizationCode(uuid, clientId, subjectId); + grant.setCode(OAuthUtils.generateRandomTokenKey()); + grant.setIssuedAt(OAuthUtils.getIssuedAt()); + grant.setExpiresIn(expiresIn); + grant.setClient(reg.getClient()); + grant.setSubject(reg.getSubject()); + + grant.setAudience(reg.getAudience()); + grant.setRedirectUri(reg.getRedirectUri()); + grant.setClientCodeVerifier(reg.getClientCodeVerifier()); + grant.setApprovedScopes(getApprovedScopes(reg.getRequestedScope(), reg.getApprovedScope())); + grant.setClientCodeVerifier(reg.getClientCodeVerifier()); + + String encrypted = serializer.encryptCodeGrant(grant, getSecretKey()); + grant.setCode(encrypted); + + storage.storeCodeGrant(grant); + return grant; + } + + @Override + public ServerAuthorizationCodeGrant removeCodeGrant(String code) { + OAuthCodeGrant codeGrant = storage.getCodeGrant(code); + ServerAuthorizationCodeGrant toReturn = null; + if (codeGrant != null) { + String encryptedCode = codeGrant.getCode(); + toReturn = serializer.decryptCodeGrant(this, encryptedCode, getSecretKey()); + storage.removeCodeGrant(codeGrant); + } + return toReturn; + } + + @Override + public ServerAccessToken createAccessToken(AccessTokenRegistration reg) { + Client client = reg.getClient(); + List<String> approvedScopes = getApprovedScopes(reg.getRequestedScope(), reg.getApprovedScope()); + List<OAuthPermission> permissions = convertScopeToPermissions(client, approvedScopes); + + long uuid = Lib.generateUuid(); + long clientId = getClientId(reg.getClient()); + long subjectId = getSubjectId(reg.getSubject()); + + OAuthTokenType type = OAuthTokenType.BEARER_TOKEN; + + AccessToken accessToken = new AccessToken(uuid, clientId, subjectId, type); + accessToken.setTokenKey(OAuthUtils.generateRandomTokenKey()); + accessToken.setIssuedAt(OAuthUtils.getIssuedAt()); + accessToken.setExpiresIn(getAccessTokenExpiration()); + accessToken.setClient(client); + accessToken.setSubject(reg.getSubject()); + + accessToken.setTokenType(type.getType()); + accessToken.setAudience(reg.getAudience()); + accessToken.setGrantType(reg.getGrantType()); + accessToken.setScopes(permissions); + + RefreshOAuthToken refreshToken = null; + if (isRefreshTokenAllowed()) { + refreshToken = newRefreshToken(accessToken, clientId, subjectId, getSecretKey()); + accessToken.setRefreshToken(refreshToken.getTokenKey()); + } + + String encryptedAccessToken = serializer.encryptAccessToken(accessToken, getSecretKey()); + accessToken.setTokenKey(encryptedAccessToken); + + if (refreshToken != null) { + storage.storeToken(accessToken, refreshToken); + storage.relateTokens(refreshToken, accessToken); + } else { + storage.storeToken(accessToken); + } + return accessToken; + } + + @Override + public ServerAccessToken getAccessToken(String accessToken) { + return serializer.decryptAccessToken(this, accessToken, getSecretKey()); + } + + @Override + public ServerAccessToken refreshAccessToken(Client client, String refreshToken, List<String> requestedScopes) { + if (!isRefreshTokenAllowed()) { + OAuthError error = new OAuthError(OAuthConstants.INVALID_REQUEST, "Refresh tokens are not allowed."); + throw new OAuthServiceException(error); + } + SecretKey secretKey = getSecretKey(); + + RefreshToken oldRefreshToken = serializer.decryptRefreshToken(this, refreshToken, secretKey); + + Iterable<OAuthToken> tokens = storage.getAccessTokensByRefreshToken(refreshToken); + storage.removeToken(tokens); + storage.removeTokenByKey(refreshToken); + + long uuid = Lib.generateUuid(); + long clientId = getClientId(oldRefreshToken.getClient()); + long subjectId = getSubjectId(oldRefreshToken.getSubject()); + + OAuthTokenType type = OAuthTokenType.BEARER_TOKEN; + + AccessToken newAccessToken = new AccessToken(uuid, clientId, subjectId, type); + newAccessToken.setTokenKey(OAuthUtils.generateRandomTokenKey()); + newAccessToken.setIssuedAt(OAuthUtils.getIssuedAt()); + newAccessToken.setExpiresIn(getAccessTokenExpiration()); + newAccessToken.setClient(oldRefreshToken.getClient()); + newAccessToken.setSubject(oldRefreshToken.getSubject()); + + newAccessToken.setTokenType(type.getType()); + newAccessToken.setAudience(oldRefreshToken.getAudience()); + newAccessToken.setGrantType(oldRefreshToken.getGrantType()); + newAccessToken.setScopes(oldRefreshToken.getScopes()); + + RefreshOAuthToken newRefreshToken = newRefreshToken(newAccessToken, clientId, subjectId, getSecretKey()); + newAccessToken.setRefreshToken(newRefreshToken.getTokenKey()); + + String newEncryptedAccessToken = serializer.encryptAccessToken(newAccessToken, secretKey); + newAccessToken.setTokenKey(newEncryptedAccessToken); + + storage.storeToken(newAccessToken, newRefreshToken); + storage.relateTokens(newRefreshToken, newAccessToken); + return newAccessToken; + } + + private RefreshOAuthToken newRefreshToken(AccessToken token, long clientId, long subjectId, SecretKey secretKey) { + long refreshUuid = Lib.generateUuid(); + + RefreshOAuthToken toReturn = new RefreshOAuthToken(refreshUuid, clientId, subjectId); + toReturn.setTokenKey(OAuthUtils.generateRandomTokenKey()); + toReturn.setIssuedAt(OAuthUtils.getIssuedAt()); + toReturn.setExpiresIn(getRefreshTokenExpiration()); + toReturn.setClient(token.getClient()); + toReturn.setSubject(token.getSubject()); + + toReturn.setAudience(token.getAudience()); + toReturn.setGrantType(token.getGrantType()); + toReturn.setScopes(token.getScopes()); + + String encryptedRefreshToken = serializer.encryptRefreshToken(toReturn, secretKey); + toReturn.setTokenKey(encryptedRefreshToken); + return toReturn; + } + + @Override + public void removeAccessToken(ServerAccessToken accessToken) { + storage.removeTokenByKey(accessToken.getTokenKey()); + } + + @Override + public void revokeToken(Client client, String tokenKey, String tokenTypeHint) { + Iterable<OAuthToken> tokens = storage.getAccessTokensByRefreshToken(tokenKey); + storage.removeToken(tokens); + storage.removeTokenByKey(tokenKey); + } + + @Override + public ServerAccessToken getPreauthorizedToken(Client client, List<String> requestedScopes, UserSubject subject, String grantType) { + // This is an optimization useful in cases where a client requests an authorization code: + // if a user has already provided a given client with a pre-authorized token then challenging + // a user with yet another form asking for the authorization is redundant + long clientId = getClientId(client); + long subjectId = getSubjectId(subject); + OAuthToken accessToken = storage.getPreauthorizedToken(clientId, subjectId, grantType); + + ServerAccessToken token = null; + if (accessToken != null) { + token = serializer.decryptAccessToken(this, accessToken.getTokenKey(), getSecretKey()); + } + return token; + } + + @Override + public List<OAuthPermission> convertScopeToPermissions(Client client, List<String> requestedScope) { + return Collections.emptyList(); + } + + private List<String> getApprovedScopes(List<String> requestedScopes, List<String> approvedScopes) { + return approvedScopes.isEmpty() ? requestedScopes : approvedScopes; + } + +}
\ No newline at end of file |