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}