使用 Nebular (Angular) 进行 Twitch OAuth

问题描述

我正在使用 Nebular 包为朋友创建自定义网站。我希望该用户必须使用 Twitch 帐户登录才能使用该站点,但我对 NbAuthModule 有一些问题。这就是我所做的

app.module.ts

import { browserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { NbThemeModule,NbLayoutModule,NbButtonModule,NbIconModule,NbSpinnerModule,NbCardModule } from '@nebular/theme';
import { browserAnimationsModule } from '@angular/platform-browser/animations';
import { NbEvaIconsModule } from '@nebular/eva-icons';
import { HttpClientModule } from '@angular/common/http';
import { NbAuthModule,NbAuthOAuth2Token,NbOAuth2AuthStrategy,NbOAuth2GrantType } from '@nebular/auth';
import { ChannelComponent } from './pages/channel/channel.component';
import { NbOAuth2CallbackComponent } from './pages/OAuth2/NbOAuth2Callback.component';
import { NbOAuth2LoginComponent } from './pages/OAuth2/NbOAuth2Login.component';

@NgModule({
  declarations: [
    AppComponent,ChannelComponent,NbOAuth2LoginComponent,NbOAuth2CallbackComponent
  ],imports: [
    browserModule,AppRoutingModule,browserAnimationsModule,NbThemeModule.forRoot({ name: 'dark' }),NbCardModule,NbAuthModule.forRoot({
      strategies:[
        NbOAuth2AuthStrategy.setup({
          clientId:'<cliend-id>',clientSecret: '<client-secret>',defaultMessages:['Successfully logged in'],name:'twitch',baseEndpoint:'https://id.twitch.tv/oauth2/',redirect:{
            success:'pages/channel',failure:'auth/error'
          },token:{
            endpoint:'token',grantType: NbOAuth2GrantType.AUTHORIZATION_CODE,class: NbAuthOAuth2Token,},authorize:{
            endpoint:'authorize',scope:'user_read',responseType: 'code',redirectUri:'http://localhost:4200/auth/callback'
          },refresh:{
            endpoint:'token',grantType: NbOAuth2GrantType.REFRESH_TOKEN
          }
        }),]
    }),NbEvaIconsModule,HttpClientModule,],providers: [],bootstrap: [AppComponent]
})
export class AppModule { }

NbOAuth2Login.component.ts

import { Component,OnDestroy } from "@angular/core";
import { NbAuthOAuth2Token,NbAuthResult,NbAuthService } from "@nebular/auth";
import { Subject } from "rxjs";
import { map,tap,takeuntil} from 'rxjs/operators';

@Component({
    selector: 'nb-oauth2-login',template: `
      <button nbButton outline *ngIf="!token" (click)="login()" status="primary" routerLink="auth/login">
      <nb-icon icon="smiling-face-outline"></nb-icon>
        Login
      </button>

      <button nbButton outline *ngIf="token" (click)="logout()">
        logout
      </button>
    `,})

export class NbOAuth2LoginComponent implements OnDestroy {
  
    private destroy$ = new Subject<void>();
    // @ts-ignore
    token: NbAuthOAuth2Token;
    
    constructor(private authService: NbAuthService){
      this.authService.onTokenChange()
      .pipe(takeuntil(this.destroy$))
      // @ts-ignore
      .subscribe((token: NbAuthOAuth2Token) => {
          // @ts-ignore
          this.token = null;
          if (token && token.isValid()) {
            this.token = token;
          }
      });
    }
  
    login() {
      this.authService.authenticate('twitch')
        .pipe(takeuntil(this.destroy$))
        .subscribe((authResult: NbAuthResult) => {
        });
    }

    logout() {
      this.authService.logout('twitch')
        .pipe(takeuntil(this.destroy$))
        .subscribe((authResult: NbAuthResult) => {
        });
    }
  
    ngOnDestroy(): void {
      this.destroy$.next();
      this.destroy$.complete();
    }
}

NbOAuth2Callback.component.ts

import { Component,OnDestroy } from "@angular/core";
import { Router } from "@angular/router";
import { NbAuthResult,takeuntil} from 'rxjs/operators';

@Component({
    selector: 'nb-playground-oauth2-callback',template: `
      <nb-layout>
        <nb-layout-column>
        <nb-card [nbSpinner]="true" nbSpinnerSize="giant" nbSpinnerStatus="info">
          <nb-card-body>
            Authenticating...
          </nb-card-body>
        </nb-card>
      </nb-layout-column>
      </nb-layout>
    `,})

export class NbOAuth2CallbackComponent implements OnDestroy {
  
    private destroy$ = new Subject<void>();
  
    constructor(private authService: NbAuthService,private router: Router) {
      this.authService.authenticate('twitch')
        .pipe(takeuntil(this.destroy$))
        .subscribe((authResult: NbAuthResult) => {
          if (authResult.isSuccess() && authResult.getRedirect()) {
            this.router.navigateByUrl(authResult.getRedirect());
          }
          else{
            this.router.navigateByUrl('auth/error');
          }
        });
    }
  
    ngOnDestroy(): void {
      this.destroy$.next();
      this.destroy$.complete();
    }
  }

我注意到,在调试模式下,使用 Login 模块时 Token 为空,但我不知道为什么

解决方法

为了解决这个问题,我在 app.module.ts

中使用以下语法添加了 2 个参数
WhenActivated