/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cxf.rs.security.oauth2.utils.crypto;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
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.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.provider.OAuthDataProvider;
import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
import org.apache.cxf.rs.security.oauth2.tokens.bearer.BearerAccessToken;
import org.apache.cxf.rs.security.oauth2.tokens.refresh.RefreshToken;
import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
import org.apache.cxf.rt.security.crypto.CryptoUtils;
public class EncryptingDataProvider implements OAuthDataProvider {
SecretKey key;
private Map<String, String> clients;
private Set<String> tokens = new HashSet<>();
private Map<String, String> refreshTokens = new HashMap<>();
public EncryptingDataProvider() throws Exception {
key = CryptoUtils.getSecretKey("AES");
String encryptedClient = ModelEncryptionSupport.encryptClient(new Client("1", "2", true), key);
clients = Collections.singletonMap("1", encryptedClient);
}
@Override
public Client getClient(String clientId) throws OAuthServiceException {
return ModelEncryptionSupport.decryptClient(clients.get(clientId), key);
}
@Override
public ServerAccessToken createAccessToken(AccessTokenRegistration accessTokenReg)
throws OAuthServiceException {
ServerAccessToken token = createAccessTokenInternal(accessTokenReg);
encryptAccessToken(token);
return token;
}
@Override
public ServerAccessToken getAccessToken(String accessTokenKey) throws OAuthServiceException {
return ModelEncryptionSupport.decryptAccessToken(this, accessTokenKey, key);
}
@Override
public ServerAccessToken refreshAccessToken(Client client, String refreshToken,
List<String> requestedScopes)
throws OAuthServiceException {
String encrypted = refreshTokens.remove(refreshToken);
ServerAccessToken token = ModelEncryptionSupport.decryptAccessToken(this, encrypted, key);
tokens.remove(token.getTokenKey());
// create a new refresh token
createRefreshToken(token);
// possibly update other token properties
encryptAccessToken(token);
return token;
}
@Override
public void revokeToken(Client client, String token, String tokenTypeHint)
throws OAuthServiceException {
// the fast way: if it is the refresh token then there will be a matching value for it
String accessToken = refreshTokens.remove(token);
// if no matching value then the token parameter is access token key
tokens.remove(accessToken == null ? token : accessToken);
}
@Override
public List<OAuthPermission> convertScopeToPermissions(Client client, List<String> requestedScope) {
// assuming that no specific scopes is documented/supported
return Collections.emptyList();
}
@Override
public ServerAccessToken getPreauthorizedToken(Client client, List<String> requestedScopes,
UserSubject subject, String grantType)
throws OAuthServiceException {
// 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
return null;
}
BearerAccessToken createAccessTokenInternal(AccessTokenRegistration accessTokenReg) {
BearerAccessToken token = new BearerAccessToken(accessTokenReg.getClient(), 3600L);
token.setSubject(accessTokenReg.getSubject());
createRefreshToken(token);
token.setGrantType(accessTokenReg.getGrantType());
token.setAudiences(accessTokenReg.getAudiences());
token.setParameters(Collections.singletonMap("param", "value"));
token.setScopes(Collections.singletonList(
new OAuthPermission("read", "read permission")));
return token;
}
private void encryptAccessToken(ServerAccessToken token) {
String encryptedToken = ModelEncryptionSupport.encryptAccessToken(token, key);
tokens.add(encryptedToken);
refreshTokens.put(token.getRefreshToken(), encryptedToken);
token.setTokenKey(encryptedToken);
}
private void createRefreshToken(ServerAccessToken token) {
RefreshToken refreshToken = new RefreshToken(token.getClient(),
"refresh",
1200L,
OAuthUtils.getIssuedAt());
String encryptedRefreshToken = ModelEncryptionSupport.encryptRefreshToken(refreshToken, key);
token.setRefreshToken(encryptedRefreshToken);
}
@Override
public List<ServerAccessToken> getAccessTokens(Client client, UserSubject sub) throws OAuthServiceException {
// TODO Auto-generated method stub
return null;
}
@Override
public List<RefreshToken> getRefreshTokens(Client client, UserSubject sub) throws OAuthServiceException {
// TODO Auto-generated method stub
return null;
}
}