OAuth2.0 e registrazione del client dinamico (utilizzando lo stack legacy OAuth di Spring Security)

1. Introduzione

In questo tutorial, prepareremo una registrazione dinamica del client con OAuth2.0. OAuth2.0 è un framework di autorizzazione che consente di ottenere un accesso limitato agli account utente su un servizio HTTP. Il client OAuth2.0 è l'applicazione che desidera accedere all'account dell'utente. Questo client può essere un'applicazione web esterna, un agente utente o solo un client nativo.

Per ottenere la registrazione dinamica del client, memorizzeremo le credenziali nel database, anziché nella configurazione hardcoded. L'applicazione che estenderemo è stata inizialmente descritta nel tutorial Spring REST API + OAuth2.

Nota : questo articolo utilizza il progetto legacy Spring OAuth.

2. Dipendenze di Maven

Per prima cosa configureremo il seguente set di dipendenze:

 org.springframework.boot spring-boot-starter-web   org.springframework spring-jdbc   org.springframework.security.oauth spring-security-oauth2 

Nota che stiamo usando spring-jdbc perché useremo un DB per memorizzare gli utenti appena registrati con password.

3. Configurazione del server OAuth2.0

Innanzitutto, dobbiamo configurare il nostro server di autorizzazione OAuth2.0. La configurazione principale è all'interno della seguente classe:

@Configuration @PropertySource({ "classpath:persistence.properties" }) @EnableAuthorizationServer public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { // config }

Ci sono alcune cose importanti che dobbiamo configurare; iniziamo con ClientDetailsServiceConfigurer:

@Override public void configure(final ClientDetailsServiceConfigurer clients) throws Exception { clients.jdbc(dataSource()) // ... }

Ciò assicurerà che stiamo usando la persistenza per ottenere le informazioni sul client.

Ovviamente impostiamo questa fonte di dati standard:

@Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName")); dataSource.setUrl(env.getProperty("jdbc.url")); dataSource.setUsername(env.getProperty("jdbc.user")); dataSource.setPassword(env.getProperty("jdbc.pass")); return dataSource; }

E così, ora, la nostra applicazione utilizzerà il database come origine dei client registrati, invece dei tipici client hardcoded in memoria.

4. Lo schema DB

Definiamo ora la struttura SQL per memorizzare i nostri client OAuth:

create table oauth_client_details ( client_id VARCHAR(256) PRIMARY KEY, resource_ids VARCHAR(256), client_secret VARCHAR(256), scope VARCHAR(256), authorized_grant_types VARCHAR(256), web_server_redirect_uri VARCHAR(256), authorities VARCHAR(256), access_token_validity INTEGER, refresh_token_validity INTEGER, additional_information VARCHAR(4096), autoapprove VARCHAR(256) );

I campi più importanti da oauth_client_details su cui dovremmo concentrarci sono:

  • client_id - per memorizzare l'ID dei client appena registrati
  • client_secret - per memorizzare la password dei client
  • access_token_validity - che indica se il client è ancora valido
  • autorità - per indicare quali ruoli sono consentiti con un particolare cliente
  • ambito - azioni consentite, ad esempio scrivere stati su Facebook ecc.
  • autorizzato_grant_types , che fornisce informazioni su come gli utenti possono accedere a un determinato client (nel nostro caso di esempio è un modulo di accesso con password)

Si noti che ogni cliente ha una relazione da uno a molti con gli utenti, il che significa naturalmente che più utenti possono utilizzare un singolo client .

5. Persistiamo alcuni client

Con la definizione dello schema SQL, possiamo finalmente creare alcuni dati nel sistema e fondamentalmente definire un client.

Utilizzeremo il seguente script data.sql , che Spring Boot verrà eseguito per impostazione predefinita, per inizializzare il DB:

INSERT INTO oauth_client_details (client_id, client_secret, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove) VALUES ("fooClientIdPassword", "secret", "foo,read,write, "password,authorization_code,refresh_token", null, null, 36000, 36000, null, true);

La descrizione dei campi più importanti in oauth_client_details è fornita nella sezione precedente.

6. Test

Per testare la registrazione dinamica del client, dobbiamo eseguire entrambi i progetti spring-security-oauth-server e spring-security-oauth-resource , rispettivamente sulle porte 8081 e 8082.

Now, we can finally write a few live tests.

Let's assume, that we registered client with id named fooClientIdPassword, that has an access to read foos.

First, we'll try to obtain an Access Token from the Auth Server, using an already defined client:

@Test public void givenDBUser_whenRevokeToken_thenAuthorized() { String accessToken = obtainAccessToken("fooClientIdPassword", "john", "123"); assertNotNull(accessToken); }

And here's the logic of obtaining the Access Token:

private String obtainAccessToken(String clientId, String username, String password) { Map params = new HashMap(); params.put("grant_type", "password"); params.put("client_id", clientId); params.put("username", username); params.put("password", password); Response response = RestAssured.given().auth().preemptive() .basic(clientId, "secret").and().with().params(params).when() .post("//localhost:8081/spring-security-oauth-server/oauth/token"); return response.jsonPath().getString("access_token"); }

7. Conclusion

In this tutorial, we learned how to dynamically register unlimited number of clients with OAuth2.0 framework.

The full implementation of this tutorial can be found over on GitHub – this is a Maven-based project, so it should be easy to import and run as it is.

Si noti che per eseguire il test, è necessario aggiungere client nel DB e che la configurazione .inMemory () non sarà più valida. Se vuoi usare il vecchio file. inMemory () config, c'è un secondo file contenente la configurazione con client hardcoded.