Aplicativo front-end com Spring Security OAuth - Fluxo do código de autorização

Aplicativo front-end com Spring Security OAuth - Fluxo do código de autorização

1. Visão geral

Neste tutorial, continuaremos nossoSpring Security OAuth series construindo um front-end simples para o fluxo do código de autorização.

Lembre-se de que o foco aqui é o cliente; dê uma olhada na redação deSpring REST API + OAuth2 + AngularJS - para revisar a configuração detalhada para os Servidores de Autorização e Recursos.

2. Servidor de Autorização

Antes de chegarmos ao nosso front end, precisamos adicionar os detalhes de nossos clientes em nossa configuração do Authorization Server:

@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/")
...

Observe como agora temos o tipo de concessão de código de autorização ativado, com os seguintes detalhes simples:

  • nosso id de cliente éfooClientId

  • nossos escopos sãofoo,read areiawrite

  • o URI de redirecionamento éhttp://localhost:8089/ (usaremos a porta 8089 para nosso aplicativo front-end)

3. O front end

Agora, vamos começar a construir nosso aplicativo front-end simples.

Como vamos usar o Angular 6 para nosso aplicativo aqui, precisamos usar o plug-infrontend-maven-plugin em nosso aplicativo 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
            
        
    

Observe que, naturalmente, precisamos instalarNode.js primeiro em nossa caixa; usaremos a CLI Angular para gerar a base para nosso aplicativo:

ng novo authCode

4. Módulo Angular

Agora, vamos discutir nosso Módulo Angular em detalhes.

Aqui está nossoAppModule simples:

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 { }

Nosso módulo consiste em três componentes e um serviço, vamos discuti-los nas seções a seguir

4.1. Componente de aplicativo

Vamos começar com nossoAppComponent, que é o componente raiz:

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

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

export class AppComponent {}

4.2. Componente residencial

A seguir está nosso componente 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(); } }

Observe que:

  • Se o usuário não estiver logado, apenas o botão de login aparecerá

  • O botão de login redireciona o usuário para o URL de autorização

  • Quando o usuário é redirecionado de volta com o código de autorização, recuperamos o token de acesso usando esse código

4.3. Componente Foo

Nosso terceiro e último componente é oFooComponent; isso exibe os recursosFoo - obtidos do servidor de recursos:

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. Serviço de aplicativo

Agora, vamos dar uma olhada emAppService:

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();
  }
}

Vamos fazer um resumo rápido de nossa implementação aqui:

  • checkCredentials(): para verificar se o usuário está logado

  • retrieveToken(): para obter o token de acesso usando o código de autorização

  • saveToken(): para salvar o token de acesso em um cookie

  • getResource(): para obter detalhes de Foo usando seu ID

  • logout(): para excluir o cookie do token de acesso

5. Execute o aplicativo

Para executar nosso aplicativo e garantir que tudo esteja funcionando corretamente, precisamos:

  • Primeiro, execute o Authorization Server na porta 8081

  • Em seguida, execute o servidor de recursos na porta 8082

  • Por fim, execute o Front End

Precisamos criar nosso aplicativo primeiro:

mvn clean install

Em seguida, altere o diretório para src / main / resources:

cd src/main/resources

Em seguida, execute nosso aplicativo na porta 8089:

npm start

6. Conclusão

Aprendemos como criar um cliente front-end simples para o fluxo do Código de Autorização usando Spring e Angular 6.

E, como sempre, o código-fonte completo está disponívelover on GitHub.