Application frontale avec Spring Security OAuth - Flux de codes d’autorisation

Application front-end avec Spring Security OAuth - Flux de codes d'autorisation

1. Vue d'ensemble

Dans ce didacticiel, nous allons poursuivre nosSpring Security OAuth series en créant une interface simple pour le flux de code d'autorisation.

Gardez à l'esprit que l'accent est mis ici sur le côté client; jetez un œil à l'écriture deSpring REST API + OAuth2 + AngularJS - pour passer en revue la configuration détaillée des serveurs d'autorisation et de ressources.

2. Serveur d'autorisation

Avant de commencer, nous devons ajouter les détails de notre client dans la configuration de notre serveur d'autorisations:

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
               .withClient("fooClientId")
               .secret(passwordEncoder().encode("secret"))
               .authorizedGrantTypes("authorization_code")
               .scopes("foo", "read", "write")
               .redirectUris("http://localhost:8089/")
...

Notez que le type d’octroi de code d’autorisation est maintenant activé, avec les détails simples suivants:

  • notre identifiant client estfooClientId

  • nos portées sontfoo,read andwrite

  • l'URI de redirection esthttp://localhost:8089/ (nous allons utiliser le port 8089 pour notre application frontale)

3. Le front end

Maintenant, commençons à créer notre application frontale simple.

Comme nous allons utiliser Angular 6 pour notre application ici, nous devons utiliser le pluginfrontend-maven-plugin dans notre application Spring Boot:


    com.github.eirslett
    frontend-maven-plugin
    1.6

    
        v8.11.3
        6.1.0
        src/main/resources
    

    
        
            install node and npm
            
                install-node-and-npm
            
        

        
            npm install
            
                npm
            
        

        
            npm run build
            
                npm
            

            
                run build
            
        
    

Notez que, naturellement, nous devons d'abord installerNode.js sur notre box; nous utiliserons la CLI angulaire pour générer la base de notre application:

ng new authCode

4. Module angulaire

Maintenant, parlons de notre module angulaire en détail.

Voici nos simplesAppModule:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule }   from '@angular/router';
import { AppComponent } from './app.component';
import { HomeComponent } from './home.component';
import { FooComponent } from './foo.component';

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    FooComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    RouterModule.forRoot([
     { path: '', component: HomeComponent, pathMatch: 'full' }], {onSameUrlNavigation: 'reload'})
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Notre module se compose de trois composants et d'un service, nous en discuterons dans les sections suivantes

4.1. Composant d'application

Commençons par notreAppComponent qui est le composant racine:

import {Component} from '@angular/core';

@Component({
    selector: 'app-root',
    template: `
`
})

export class AppComponent {}

4.2. Composant maison

Vient ensuite notre composant principal,HomeComponent:

import {Component} from '@angular/core';
import {AppService} from './app.service'

@Component({
    selector: 'home-header',
    providers: [AppService],
  template: `
Welcome !! Logout
` }) export class HomeComponent { public isLoggedIn = false; constructor( private _service:AppService){} ngOnInit(){ this.isLoggedIn = this._service.checkCredentials(); let i = window.location.href.indexOf('code'); if(!this.isLoggedIn && i != -1){ this._service.retrieveToken(window.location.href.substring(i + 5)); } } login() { window.location.href = 'http://localhost:8081/spring-security-oauth-server/oauth/authorize?response_type=code&client_id=' + this._service.clientId + '&redirect_uri='+ this._service.redirectUri; } logout() { this._service.logout(); } }

Notez que:

  • Si l'utilisateur n'est pas connecté, seul le bouton de connexion apparaîtra

  • Le bouton de connexion redirige l'utilisateur vers l'URL d'autorisation

  • Lorsque l'utilisateur est redirigé avec le code d'autorisation, nous récupérons le jeton d'accès à l'aide de ce code

4.3. Composant Foo

Notre troisième et dernier composant est leFooComponent; cela affiche les ressourcesFoo - obtenues à partir du serveur de ressources:

import { Component } from '@angular/core';
import {AppService, Foo} from './app.service'

@Component({
  selector: 'foo-details',
  providers: [AppService],
  template: `

Foo Details

{{foo.id}}
{{foo.name}}
` }) export class FooComponent { public foo = new Foo(1,'sample foo'); private foosUrl = 'http://localhost:8082/spring-security-oauth-resource/foos/'; constructor(private _service:AppService) {} getFoo(){ this._service.getResource(this.foosUrl+this.foo.id) .subscribe( data => this.foo = data, error => this.foo.name = 'Error'); } }

4.4. Service d'application

Voyons maintenant lesAppService:

import {Injectable} from '@angular/core';
import { Cookie } from 'ng2-cookies';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

export class Foo {
  constructor(
    public id: number,
    public name: string) { }
}

@Injectable()
export class AppService {
   public clientId = 'fooClientId';
   public redirectUri = 'http://localhost:8089/';

  constructor(
    private _http: HttpClient){}

  retrieveToken(code){
    let params = new URLSearchParams();
    params.append('grant_type','authorization_code');
    params.append('client_id', this.clientId);
    params.append('redirect_uri', this.redirectUri);
    params.append('code',code);

    let headers = new HttpHeaders({'Content-type': 'application/x-www-form-urlencoded; charset=utf-8', 'Authorization': 'Basic '+btoa(this.clientId+":secret")});
     this._http.post('http://localhost:8081/spring-security-oauth-server/oauth/token', params.toString(), { headers: headers })
    .subscribe(
      data => this.saveToken(data),
      err => alert('Invalid Credentials')
    );
  }

  saveToken(token){
    var expireDate = new Date().getTime() + (1000 * token.expires_in);
    Cookie.set("access_token", token.access_token, expireDate);
    console.log('Obtained Access token');
    window.location.href = 'http://localhost:8089';
  }

  getResource(resourceUrl) : Observable{
    var headers = new HttpHeaders({'Content-type': 'application/x-www-form-urlencoded; charset=utf-8', 'Authorization': 'Bearer '+Cookie.get('access_token')});
    return this._http.get(resourceUrl,{ headers: headers })
                   .catch((error:any) => Observable.throw(error.json().error || 'Server error'));
  }

  checkCredentials(){
    return Cookie.check('access_token');
  }

  logout() {
    Cookie.delete('access_token');
    window.location.reload();
  }
}

Faisons un bref aperçu de notre mise en œuvre ici:

  • checkCredentials(): pour vérifier si l'utilisateur est connecté

  • retrieveToken(): pour obtenir un jeton d'accès à l'aide du code d'autorisation

  • saveToken(): pour enregistrer le jeton d'accès dans un cookie

  • getResource(): pour obtenir les détails de Foo en utilisant son ID

  • logout(): pour supprimer le cookie de jeton d'accès

5. Lancer l'application

Pour exécuter notre application et vous assurer que tout fonctionne correctement, nous devons:

  • Tout d'abord, exécutez Authorization Server sur le port 8081.

  • Ensuite, exécutez le serveur de ressources sur le port 8082.

  • Enfin, lancez le Front End

Nous devrons d'abord créer notre application:

mvn clean install

Puis changez de répertoire en src / main / resources:

cd src/main/resources

Ensuite, lancez notre application sur le port 8089:

npm start

6. Conclusion

Nous avons appris à créer un client frontal simple pour le flux de codes d'autorisation à l'aide de Spring et Angular 6.

Et, comme toujours, le code source complet est disponibleover on GitHub.