001/******************************************************************************* 002 * Copyright 2017 The MIT Internet Trust Consortium 003 * 004 * Portions copyright 2011-2013 The MITRE Corporation 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 *******************************************************************************/ 018package org.mitre.oauth2.service.impl; 019 020import java.math.BigInteger; 021import java.security.SecureRandom; 022import java.util.Collection; 023import java.util.HashSet; 024 025import org.mitre.oauth2.model.ClientDetailsEntity; 026import org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod; 027import org.mitre.oauth2.service.ClientDetailsEntityService; 028import org.mitre.openid.connect.config.ConfigurationPropertiesBean; 029import org.springframework.beans.factory.annotation.Autowired; 030import org.springframework.security.core.GrantedAuthority; 031import org.springframework.security.core.authority.SimpleGrantedAuthority; 032import org.springframework.security.core.userdetails.User; 033import org.springframework.security.core.userdetails.UserDetails; 034import org.springframework.security.core.userdetails.UserDetailsService; 035import org.springframework.security.core.userdetails.UsernameNotFoundException; 036import org.springframework.security.oauth2.common.exceptions.InvalidClientException; 037import org.springframework.stereotype.Service; 038 039import com.google.common.base.Strings; 040 041/** 042 * Shim layer to convert a ClientDetails service into a UserDetails service 043 * 044 * @author AANGANES 045 * 046 */ 047@Service("clientUserDetailsService") 048public class DefaultClientUserDetailsService implements UserDetailsService { 049 050 private static GrantedAuthority ROLE_CLIENT = new SimpleGrantedAuthority("ROLE_CLIENT"); 051 052 @Autowired 053 private ClientDetailsEntityService clientDetailsService; 054 055 @Autowired 056 private ConfigurationPropertiesBean config; 057 058 @Override 059 public UserDetails loadUserByUsername(String clientId) throws UsernameNotFoundException { 060 061 try { 062 ClientDetailsEntity client = clientDetailsService.loadClientByClientId(clientId); 063 064 if (client != null) { 065 066 String password = Strings.nullToEmpty(client.getClientSecret()); 067 068 if (config.isHeartMode() || // if we're running HEART mode turn off all client secrets 069 (client.getTokenEndpointAuthMethod() != null && 070 (client.getTokenEndpointAuthMethod().equals(AuthMethod.PRIVATE_KEY) || 071 client.getTokenEndpointAuthMethod().equals(AuthMethod.SECRET_JWT)))) { 072 073 // Issue a random password each time to prevent password auth from being used (or skipped) 074 // for private key or shared key clients, see #715 075 076 password = new BigInteger(512, new SecureRandom()).toString(16); 077 } 078 079 boolean enabled = true; 080 boolean accountNonExpired = true; 081 boolean credentialsNonExpired = true; 082 boolean accountNonLocked = true; 083 Collection<GrantedAuthority> authorities = new HashSet<>(client.getAuthorities()); 084 authorities.add(ROLE_CLIENT); 085 086 return new User(clientId, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities); 087 } else { 088 throw new UsernameNotFoundException("Client not found: " + clientId); 089 } 090 } catch (InvalidClientException e) { 091 throw new UsernameNotFoundException("Client not found: " + clientId); 092 } 093 094 } 095 096 public ClientDetailsEntityService getClientDetailsService() { 097 return clientDetailsService; 098 } 099 100 public void setClientDetailsService(ClientDetailsEntityService clientDetailsService) { 101 this.clientDetailsService = clientDetailsService; 102 } 103 104}