Skip to content
This repository has been archived by the owner on May 31, 2022. It is now read-only.

Commit

Permalink
SECOAUTH-254: add list clients to regsitration service
Browse files Browse the repository at this point in the history
  • Loading branch information
dsyer committed May 14, 2012
1 parent b7a928a commit 512c02b
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 45 deletions.
@@ -0,0 +1,44 @@
/*
* Copyright 2002-2011 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.common.util;

import java.util.List;
import java.util.Map;

import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;

/**
* @author Dave Syer
*
*/
public class DefaultJdbcListFactory implements JdbcListFactory {

private final NamedParameterJdbcOperations jdbcTemplate;

/**
* @param jdbcTemplate the jdbc template to use
*/
public DefaultJdbcListFactory(NamedParameterJdbcOperations jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}

public <T> List<T> getList(String sql, Map<String, Object> parameters, RowMapper<T> rowMapper) {
return jdbcTemplate.query(sql, parameters, rowMapper);
}

}
@@ -0,0 +1,37 @@
/*
* Copyright 2002-2011 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.common.util;

import java.util.List;
import java.util.Map;

import org.springframework.jdbc.core.RowMapper;

/**
* @author Dave Syer
*
*/
public interface JdbcListFactory {

/**
* @param sql
* @param parameters
* @return a list of {@link T}
*/
<T> List<T> getList(String sql, Map<String, Object> parameters, RowMapper<T> rowMapper);

}
Expand Up @@ -15,6 +15,8 @@
*/
package org.springframework.security.oauth2.provider;

import java.util.List;

/**
* Interface for client registration, handling add, update and remove of {@link ClientDetails} from an Authorization
* Server.
Expand All @@ -30,6 +32,8 @@ public interface ClientRegistrationService {

void updateClientSecret(String clientId, String secret) throws NoSuchClientException;

void removeClientDetails(ClientDetails clientDetails) throws NoSuchClientException;
void removeClientDetails(String clientId) throws NoSuchClientException;

List<ClientDetails> listClientDetails();

}
Expand Up @@ -18,16 +18,21 @@

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;

import javax.sql.DataSource;

import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
import org.springframework.security.oauth2.common.util.DefaultJdbcListFactory;
import org.springframework.security.oauth2.common.util.JdbcListFactory;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

Expand All @@ -37,11 +42,15 @@
public class JdbcClientDetailsService implements ClientDetailsService, ClientRegistrationService {

private static final String CLIENT_FIELDS = "resource_ids, client_secret, scope, "
+ "authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, "
+ "refresh_token_validity";
+ "authorized_grant_types, web_server_redirect_uri, authorities, "
+ "access_token_validity, refresh_token_validity";

private static final String BASE_FIND_STATEMENT = "select client_id, " + CLIENT_FIELDS
+ " from oauth_client_details";

private static final String DEFAULT_FIND_STATEMENT = BASE_FIND_STATEMENT + " order by client_id";

private static final String DEFAULT_SELECT_STATEMENT = "select client_id, " + CLIENT_FIELDS
+ " from oauth_client_details where client_id = ?";
private static final String DEFAULT_SELECT_STATEMENT = BASE_FIND_STATEMENT + " where client_id = ?";

private static final String DEFAULT_INSERT_STATEMENT = "insert into oauth_client_details (" + CLIENT_FIELDS
+ ", client_id) values (?,?,?,?,?,?,?,?,?)";
Expand All @@ -50,20 +59,24 @@ public class JdbcClientDetailsService implements ClientDetailsService, ClientReg
+ "authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, "
+ "refresh_token_validity";

private static final String DEFAULT_UPDATE_STATEMENT = "update oauth_client_details "
+ "set " + CLIENT_FIELDS_FOR_UPDATE.replaceAll(", ", "=?, ")+"=? where client_id = ?";
private static final String DEFAULT_UPDATE_STATEMENT = "update oauth_client_details " + "set "
+ CLIENT_FIELDS_FOR_UPDATE.replaceAll(", ", "=?, ") + "=? where client_id = ?";

private static final String DEFAULT_UPDATE_SECRET_STATEMENT = "update oauth_client_details "
+ "set client_secret = ? where client_id = ?";

private static final String DEFAULT_DELETE_STATEMENT = "delete from oauth_client_details where client_id = ?";

private RowMapper<ClientDetails> rowMapper = new ClientDetailsRowMapper();

private String deleteClientDetailsSql = DEFAULT_DELETE_STATEMENT;

private String findClientDetailsSql = DEFAULT_FIND_STATEMENT;

private String updateClientDetailsSql = DEFAULT_UPDATE_STATEMENT;

private String updateClientSecretSql = DEFAULT_UPDATE_SECRET_STATEMENT;

private String insertClientDetailsSql = DEFAULT_INSERT_STATEMENT;

private String selectClientDetailsSql = DEFAULT_SELECT_STATEMENT;
Expand All @@ -72,9 +85,12 @@ public class JdbcClientDetailsService implements ClientDetailsService, ClientReg

private final JdbcTemplate jdbcTemplate;

private JdbcListFactory listFactory;

public JdbcClientDetailsService(DataSource dataSource) {
Assert.notNull(dataSource, "DataSource required");
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.listFactory = new DefaultJdbcListFactory(new NamedParameterJdbcTemplate(jdbcTemplate));
}

/**
Expand All @@ -87,17 +103,7 @@ public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
public ClientDetails loadClientByClientId(String clientId) throws InvalidClientException {
ClientDetails details;
try {
details = jdbcTemplate.queryForObject(selectClientDetailsSql, new RowMapper<ClientDetails>() {
public ClientDetails mapRow(ResultSet rs, int rowNum) throws SQLException {
BaseClientDetails details = new BaseClientDetails(rs.getString(2), rs.getString(4),
rs.getString(5), rs.getString(7), rs.getString(6));
details.setClientId(rs.getString(1));
details.setClientSecret(rs.getString(3));
details.setAccessTokenValiditySeconds(rs.getInt(8));
details.setRefreshTokenValiditySeconds(rs.getInt(9));
return details;
}
}, clientId);
details = jdbcTemplate.queryForObject(selectClientDetailsSql, new ClientDetailsRowMapper(), clientId);
}
catch (EmptyResultDataAccessException e) {
throw new InvalidClientException("Client not found: " + clientId);
Expand All @@ -121,46 +127,55 @@ public void updateClientDetails(ClientDetails clientDetails) throws NoSuchClient
throw new NoSuchClientException("No client found with id = " + clientDetails.getClientId());
}
}

public void updateClientSecret(String clientId, String secret) throws NoSuchClientException {
int count = jdbcTemplate.update(updateClientSecretSql, secret, clientId);
if (count != 1) {
throw new NoSuchClientException("No client found with id = " + clientId);
}
}

public void removeClientDetails(ClientDetails clientDetails) throws NoSuchClientException {
int count = jdbcTemplate.update(deleteClientDetailsSql, clientDetails.getClientId());
public void removeClientDetails(String clientId) throws NoSuchClientException {
int count = jdbcTemplate.update(deleteClientDetailsSql, clientId);
if (count != 1) {
throw new NoSuchClientException("No client found with id = " + clientDetails.getClientId());
throw new NoSuchClientException("No client found with id = " + clientId);
}
}

public List<ClientDetails> listClientDetails() {
return listFactory.getList(findClientDetailsSql, Collections.<String, Object> emptyMap(), rowMapper);
}

private Object[] getFields(ClientDetails clientDetails) {
return new Object[] {
clientDetails.getResourceIds()!=null ? StringUtils.collectionToCommaDelimitedString(clientDetails.getResourceIds()) : null,
clientDetails.getClientSecret()!=null ? passwordEncoder.encode(clientDetails.getClientSecret()) : null,
clientDetails.getScope()!=null ? StringUtils.collectionToCommaDelimitedString(clientDetails.getScope()) : null,
clientDetails.getAuthorizedGrantTypes()!=null ? StringUtils.collectionToCommaDelimitedString(clientDetails.getAuthorizedGrantTypes()) : null,
clientDetails.getRegisteredRedirectUri()!=null ? StringUtils.collectionToCommaDelimitedString(clientDetails.getRegisteredRedirectUri()) : null,
clientDetails.getAuthorities()!=null ? StringUtils.collectionToCommaDelimitedString(clientDetails.getAuthorities()) : null,
clientDetails.getAccessTokenValiditySeconds(),
clientDetails.getRefreshTokenValiditySeconds(),
clientDetails.getClientId()
};
clientDetails.getResourceIds() != null ? StringUtils.collectionToCommaDelimitedString(clientDetails
.getResourceIds()) : null,
clientDetails.getClientSecret() != null ? passwordEncoder.encode(clientDetails.getClientSecret())
: null,
clientDetails.getScope() != null ? StringUtils.collectionToCommaDelimitedString(clientDetails
.getScope()) : null,
clientDetails.getAuthorizedGrantTypes() != null ? StringUtils
.collectionToCommaDelimitedString(clientDetails.getAuthorizedGrantTypes()) : null,
clientDetails.getRegisteredRedirectUri() != null ? StringUtils
.collectionToCommaDelimitedString(clientDetails.getRegisteredRedirectUri()) : null,
clientDetails.getAuthorities() != null ? StringUtils.collectionToCommaDelimitedString(clientDetails
.getAuthorities()) : null, clientDetails.getAccessTokenValiditySeconds(),
clientDetails.getRefreshTokenValiditySeconds(), clientDetails.getClientId() };
}

private Object[] getFieldsForUpdate(ClientDetails clientDetails) {
return new Object[] {
clientDetails.getResourceIds()!=null ? StringUtils.collectionToCommaDelimitedString(clientDetails.getResourceIds()) : null,
clientDetails.getScope()!=null ? StringUtils.collectionToCommaDelimitedString(clientDetails.getScope()) : null,
clientDetails.getAuthorizedGrantTypes()!=null ? StringUtils.collectionToCommaDelimitedString(clientDetails.getAuthorizedGrantTypes()) : null,
clientDetails.getRegisteredRedirectUri()!=null ? StringUtils.collectionToCommaDelimitedString(clientDetails.getRegisteredRedirectUri()) : null,
clientDetails.getAuthorities()!=null ? StringUtils.collectionToCommaDelimitedString(clientDetails.getAuthorities()) : null,
clientDetails.getAccessTokenValiditySeconds(),
clientDetails.getRefreshTokenValiditySeconds(),
clientDetails.getClientId()
};
clientDetails.getResourceIds() != null ? StringUtils.collectionToCommaDelimitedString(clientDetails
.getResourceIds()) : null,
clientDetails.getScope() != null ? StringUtils.collectionToCommaDelimitedString(clientDetails
.getScope()) : null,
clientDetails.getAuthorizedGrantTypes() != null ? StringUtils
.collectionToCommaDelimitedString(clientDetails.getAuthorizedGrantTypes()) : null,
clientDetails.getRegisteredRedirectUri() != null ? StringUtils
.collectionToCommaDelimitedString(clientDetails.getRegisteredRedirectUri()) : null,
clientDetails.getAuthorities() != null ? StringUtils.collectionToCommaDelimitedString(clientDetails
.getAuthorities()) : null, clientDetails.getAccessTokenValiditySeconds(),
clientDetails.getRefreshTokenValiditySeconds(), clientDetails.getClientId() };
}

public void setSelectClientDetailsSql(String selectClientDetailsSql) {
Expand All @@ -174,7 +189,7 @@ public void setDeleteClientDetailsSql(String deleteClientDetailsSql) {
public void setUpdateClientDetailsSql(String updateClientDetailsSql) {
this.updateClientDetailsSql = updateClientDetailsSql;
}

public void setUpdateClientSecretSql(String updateClientSecretSql) {
this.updateClientSecretSql = updateClientSecretSql;
}
Expand All @@ -183,4 +198,40 @@ public void setInsertClientDetailsSql(String insertClientDetailsSql) {
this.insertClientDetailsSql = insertClientDetailsSql;
}

public void setFindClientDetailsSql(String findClientDetailsSql) {
this.findClientDetailsSql = findClientDetailsSql;
}

/**
* @param listFactory the list factory to set
*/
public void setListFactory(JdbcListFactory listFactory) {
this.listFactory = listFactory;
}

/**
* @param rowMapper the rowMapper to set
*/
public void setRowMapper(RowMapper<ClientDetails> rowMapper) {
this.rowMapper = rowMapper;
}

/**
* Row mapper for ClientDetails.
*
* @author Dave Syer
*
*/
private static class ClientDetailsRowMapper implements RowMapper<ClientDetails> {
public ClientDetails mapRow(ResultSet rs, int rowNum) throws SQLException {
BaseClientDetails details = new BaseClientDetails(rs.getString(2), rs.getString(4), rs.getString(5),
rs.getString(7), rs.getString(6));
details.setClientId(rs.getString(1));
details.setClientSecret(rs.getString(3));
details.setAccessTokenValiditySeconds(rs.getInt(8));
details.setRefreshTokenValiditySeconds(rs.getInt(9));
return details;
}
}

}
Expand Up @@ -232,7 +232,7 @@ public void testRemoveClient() {
clientDetails.setClientId("deletedClientIdWithNoDetails");

service.addClientDetails(clientDetails);
service.removeClientDetails(clientDetails);
service.removeClientDetails(clientDetails.getClientId());

int count = jdbcTemplate.queryForInt("select count(*) from oauth_client_details where client_id=?", "deletedClientIdWithNoDetails");

Expand All @@ -245,7 +245,19 @@ public void testRemoveNonExistentClient() {
BaseClientDetails clientDetails = new BaseClientDetails();
clientDetails.setClientId("nosuchClientIdWithNoDetails");

service.removeClientDetails(clientDetails);
service.removeClientDetails(clientDetails.getClientId());
}

@Test
public void testFindClients() {

BaseClientDetails clientDetails = new BaseClientDetails();
clientDetails.setClientId("aclient");

service.addClientDetails(clientDetails);
int count = service.listClientDetails().size();

assertEquals(1, count);
}

}

0 comments on commit 512c02b

Please sign in to comment.