/* * Copyright 2002-2013 the original author or authors. * * Licensed 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.springframework.security.oauth2.config.annotation.builders; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.springframework.security.config.annotation.SecurityBuilder; import org.springframework.security.config.annotation.SecurityConfigurerAdapter; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.client.BaseClientDetails; /** * Builder for OAuth2 client details service. Can be used to construct either an in-memory or a JDBC implementation of * the {@link ClientDetailsService} and populate it with data. * * @author Dave Syer * */ public class ClientDetailsServiceBuilder<B extends ClientDetailsServiceBuilder<B>> extends SecurityConfigurerAdapter<ClientDetailsService, B> implements SecurityBuilder<ClientDetailsService> { private List<ClientBuilder> clientBuilders = new ArrayList<ClientBuilder>(); public InMemoryClientDetailsServiceBuilder inMemory() throws Exception { return new InMemoryClientDetailsServiceBuilder(); } public JdbcClientDetailsServiceBuilder jdbc() throws Exception { return new JdbcClientDetailsServiceBuilder(); } @SuppressWarnings("rawtypes") public ClientDetailsServiceBuilder<?> clients(final ClientDetailsService clientDetailsService) throws Exception { return new ClientDetailsServiceBuilder() { @Override public ClientDetailsService build() throws Exception { return clientDetailsService; } }; } public ClientBuilder withClient(String clientId) { ClientBuilder clientBuilder = new ClientBuilder(clientId); this.clientBuilders.add(clientBuilder); return clientBuilder; } @Override public ClientDetailsService build() throws Exception { for (ClientBuilder clientDetailsBldr : clientBuilders) { addClient(clientDetailsBldr.clientId, clientDetailsBldr.build()); } return performBuild(); } protected void addClient(String clientId, ClientDetails build) { } protected ClientDetailsService performBuild() { throw new UnsupportedOperationException("Cannot build client services (maybe use inMemory() or jdbc())."); } public final class ClientBuilder { private final String clientId; private Collection<String> authorizedGrantTypes = new LinkedHashSet<String>(); private Collection<String> authorities = new LinkedHashSet<String>(); private Integer accessTokenValiditySeconds; private Integer refreshTokenValiditySeconds; private Collection<String> scopes = new LinkedHashSet<String>(); private Collection<String> autoApproveScopes = new HashSet<String>(); private String secret; private Set<String> registeredRedirectUris = new HashSet<String>(); private Set<String> resourceIds = new HashSet<String>(); private boolean autoApprove; private Map<String, Object> additionalInformation = new LinkedHashMap<String, Object>(); private ClientDetails build() { BaseClientDetails result = new BaseClientDetails(); result.setClientId(clientId); result.setAuthorizedGrantTypes(authorizedGrantTypes); result.setAccessTokenValiditySeconds(accessTokenValiditySeconds); result.setRefreshTokenValiditySeconds(refreshTokenValiditySeconds); result.setRegisteredRedirectUri(registeredRedirectUris); result.setClientSecret(secret); result.setScope(scopes); result.setAuthorities(AuthorityUtils.createAuthorityList(authorities.toArray(new String[authorities.size()]))); result.setResourceIds(resourceIds); result.setAdditionalInformation(additionalInformation); if (autoApprove) { result.setAutoApproveScopes(scopes); } else { result.setAutoApproveScopes(autoApproveScopes); } return result; } public ClientBuilder resourceIds(String... resourceIds) { for (String resourceId : resourceIds) { this.resourceIds.add(resourceId); } return this; } public ClientBuilder redirectUris(String... registeredRedirectUris) { for (String redirectUri : registeredRedirectUris) { this.registeredRedirectUris.add(redirectUri); } return this; } public ClientBuilder authorizedGrantTypes(String... authorizedGrantTypes) { for (String grant : authorizedGrantTypes) { this.authorizedGrantTypes.add(grant); } return this; } public ClientBuilder accessTokenValiditySeconds(int accessTokenValiditySeconds) { this.accessTokenValiditySeconds = accessTokenValiditySeconds; return this; } public ClientBuilder refreshTokenValiditySeconds(int refreshTokenValiditySeconds) { this.refreshTokenValiditySeconds = refreshTokenValiditySeconds; return this; } public ClientBuilder secret(String secret) { this.secret = secret; return this; } public ClientBuilder scopes(String... scopes) { for (String scope : scopes) { this.scopes.add(scope); } return this; } public ClientBuilder authorities(String... authorities) { for (String authority : authorities) { this.authorities.add(authority); } return this; } public ClientBuilder autoApprove(boolean autoApprove) { this.autoApprove = autoApprove; return this; } public ClientBuilder autoApprove(String... scopes) { for (String scope : scopes) { this.autoApproveScopes.add(scope); } return this; } public ClientBuilder additionalInformation(Map<String, ?> map) { this.additionalInformation.putAll(map); return this; } public ClientBuilder additionalInformation(String... pairs) { for (String pair : pairs) { String separator = ":"; if (!pair.contains(separator) && pair.contains("=")) { separator = "="; } int index = pair.indexOf(separator); String key = pair.substring(0, index > 0 ? index : pair.length()); String value = index > 0 ? pair.substring(index+1) : null; this.additionalInformation.put(key, (Object) value); } return this; } public ClientDetailsServiceBuilder<B> and() { return ClientDetailsServiceBuilder.this; } private ClientBuilder(String clientId) { this.clientId = clientId; } } }