/** * 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); } } }