/**
* 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.provider;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.crypto.SecretKey;
import org.apache.cxf.rs.security.oauth2.common.Client;
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.tokens.refresh.RefreshToken;
import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
import org.apache.cxf.rs.security.oauth2.utils.crypto.ModelEncryptionSupport;
import org.apache.cxf.rt.security.crypto.CryptoUtils;
import org.apache.cxf.rt.security.crypto.KeyProperties;
public class DefaultEncryptingOAuthDataProvider extends AbstractOAuthDataProvider {
protected SecretKey key;
private Set<String> tokens = Collections.synchronizedSet(new HashSet<>());
private Set<String> refreshTokens = Collections.synchronizedSet(new HashSet<>());
private ConcurrentHashMap<String, String> clientsMap = new ConcurrentHashMap<String, String>();
public DefaultEncryptingOAuthDataProvider(String algo, int keySize) {
this(new KeyProperties(algo, keySize));
}
public DefaultEncryptingOAuthDataProvider(KeyProperties props) {
this(CryptoUtils.getSecretKey(props));
}
public DefaultEncryptingOAuthDataProvider(SecretKey key) {
this.key = key;
}
@Override
public Client doGetClient(String clientId) throws OAuthServiceException {
return ModelEncryptionSupport.decryptClient(clientsMap.get(clientId), key);
}
@Override
public void setClient(Client client) {
clientsMap.put(client.getClientId(), ModelEncryptionSupport.encryptClient(client, key));
}
@Override
public void doRemoveClient(Client c) {
clientsMap.remove(c.getClientId());
}
@Override
public List<Client> getClients(UserSubject resourceOwner) {
List<Client> clients = new ArrayList<>(clientsMap.size());
for (String clientKey : clientsMap.keySet()) {
Client c = getClient(clientKey);
if (isClientMatched(c, resourceOwner)) {
clients.add(c);
}
}
return clients;
}
@Override
public List<ServerAccessToken> getAccessTokens(Client c, UserSubject sub) {
List<ServerAccessToken> list = new ArrayList<>(tokens.size());
for (String tokenKey : tokens) {
ServerAccessToken token = getAccessToken(tokenKey);
if (isTokenMatched(token, c, sub)) {
list.add(token);
}
}
return list;
}
@Override
public List<RefreshToken> getRefreshTokens(Client c, UserSubject sub) {
List<RefreshToken> list = new ArrayList<>(refreshTokens.size());
for (String tokenKey : refreshTokens) {
RefreshToken token = getRefreshToken(tokenKey);
if (isTokenMatched(token, c, sub)) {
list.add(token);
}
}
return list;
}
@Override
public ServerAccessToken getAccessToken(String accessToken) throws OAuthServiceException {
try {
return ModelEncryptionSupport.decryptAccessToken(this, accessToken, key);
} catch (SecurityException ex) {
throw new OAuthServiceException(OAuthConstants.ACCESS_DENIED, ex);
}
}
@Override
protected void saveAccessToken(ServerAccessToken serverToken) {
encryptAccessToken(serverToken);
}
@Override
protected void doRevokeAccessToken(ServerAccessToken at) {
tokens.remove(at.getTokenKey());
}
@Override
protected void saveRefreshToken(RefreshToken refreshToken) {
String encryptedRefreshToken = ModelEncryptionSupport.encryptRefreshToken(refreshToken, key);
refreshToken.setTokenKey(encryptedRefreshToken);
refreshTokens.add(encryptedRefreshToken);
}
@Override
protected void doRevokeRefreshToken(RefreshToken rt) {
refreshTokens.remove(rt.getTokenKey());
}
private void encryptAccessToken(ServerAccessToken token) {
String encryptedToken = ModelEncryptionSupport.encryptAccessToken(token, key);
tokens.add(encryptedToken);
token.setTokenKey(encryptedToken);
}
@Override
protected RefreshToken getRefreshToken(String refreshTokenKey) {
try {
return ModelEncryptionSupport.decryptRefreshToken(this, refreshTokenKey, key);
} catch (SecurityException ex) {
throw new OAuthServiceException(OAuthConstants.ACCESS_DENIED, ex);
}
}
}