Home > Back-end >  How to Pass Cognito JWT Token in HttpInteceptor in Angular
How to Pass Cognito JWT Token in HttpInteceptor in Angular

Time:09-29

I currently have an application that uses Cognito for user login and authentication

This is what I'm using for the the user Authentication

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import Amplify, { Auth } from 'aws-amplify';

import { environment } from '../environments/environment';

export interface IUser {
  email: string;
  password: string;
  showPassword: boolean;
  code: string;
  name: string;
}

@Injectable({
  providedIn: 'root',
})
export class CognitoService {

  private authenticationSubject: BehaviorSubject<any>;

  Tokentest: string = '';

  constructor() {
    Amplify.configure({
      Auth: environment.cognito
    });

    this.authenticationSubject = new BehaviorSubject<boolean>(false);
  }

  public signUp(user: IUser): Promise<any> {
    return Auth.signUp({
      username: user.email,
      password: user.password,
    });
  }

  public confirmSignUp(user: IUser): Promise<any> {
    return Auth.confirmSignUp(user.email, user.code);
  }

  public signIn(user: IUser): Promise<any> {

    return Auth.signIn(user.email, user.password)
    .then((user) => {
      this.authenticationSubject.next(true);
      let Token = user.getSignInUserSession().getAccessToken().getJwtToken();
      console.log(Token);
      this.Tokentest = Token;
    });
    
  }

  public signOut(): Promise<any> {
    return Auth.signOut()
    .then(() => {
      this.authenticationSubject.next(false);
    });
  }

  public isAuthenticated(): Promise<boolean> {
    if (this.authenticationSubject.value) {
      return Promise.resolve(true);
    } else {
      return this.getUser()
      .then((user: any) => {
        if (user) {
          return true;
        } else {
          return false;
        }
      }).catch(() => {
        return false;
      });
    }
  }

  public getUser(): Promise<any> {
    return Auth.currentUserInfo();
  }

  public updateUser(user: IUser): Promise<any> {
    return Auth.currentUserPoolUser()
    .then((cognitoUser: any) => {
      return Auth.updateUserAttributes(cognitoUser, user);
    });
  }

}

I then have a token interceptor service that looks at any http request and passes the jwt token in the header

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import Amplify, { Auth} from 'aws-amplify';
import { IUser, CognitoService } from '../cognito.service';

@Injectable({
  providedIn: 'root'
})

export class TokenInteceptorService implements HttpInterceptor {


  constructor() { }
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    ///
    let token = localStorage.getItem('{the key for the jwt token}')
    let jwttoken = req.clone({
     setHeaders:{
       Authorization: 'Bearer '   token
     } 
    })
    return next.handle(jwttoken);
  }
}

My issue is that thus far I have getting the key for the token value that is set in localStorage using getItem and passing that key value into the header.

This does not work if I have multiple users as each key will be different.

How would I go about passing the jwt token via the interceptor no matter who is logged in.

Any help would be greatly appreciated

CodePudding user response:

You should inject your CognitoService to your Interceptor as following:

import {
  HttpEvent,
  HttpHandler,
  HttpInterceptor,
  HttpRequest,
} from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, from, switchMap } from 'rxjs';
import Amplify, { Auth } from 'aws-amplify';
import { IUser, CognitoService } from '../cognito.service';

@Injectable({
  providedIn: 'root',
})
export class TokenInteceptorService implements HttpInterceptor {
  constructor(private readonly _cognitoService: CognitoService) {}

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    //
    return from(this._cognitoService.getSession()).pipe(
      switchMap((session) => {
        let jwttoken = req.clone({
          setHeaders: {
            Authorization: 'Bearer '   session.accessToken.jwtToken,
          },
        });
        return next.handle(jwttoken);
      })
    );
  }
}

and then in your CognitoService you have to provide getSession() function:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import Amplify, { Auth } from 'aws-amplify';

import { environment } from '../environments/environment';

export interface IUser {
  email: string;
  password: string;
  showPassword: boolean;
  code: string;
  name: string;
}

@Injectable({
  providedIn: 'root',
})
export class CognitoService {
  private authenticationSubject: BehaviorSubject<any>;

  Tokentest: string = '';

  constructor() {
    Amplify.configure({
      Auth: environment.cognito,
    });

    this.authenticationSubject = new BehaviorSubject<boolean>(false);
  }

  public signUp(user: IUser): Promise<any> {
    return Auth.signUp({
      username: user.email,
      password: user.password,
    });
  }

  public confirmSignUp(user: IUser): Promise<any> {
    return Auth.confirmSignUp(user.email, user.code);
  }

  public signIn(user: IUser): Promise<any> {
    return Auth.signIn(user.email, user.password).then((user) => {
      this.authenticationSubject.next(true);
      let Token = user.getSignInUserSession().getAccessToken().getJwtToken();
      console.log(Token);
      this.Tokentest = Token;
    });
  }

  public signOut(): Promise<any> {
    return Auth.signOut().then(() => {
      this.authenticationSubject.next(false);
    });
  }

  public isAuthenticated(): Promise<boolean> {
    if (this.authenticationSubject.value) {
      return Promise.resolve(true);
    } else {
      return this.getUser()
        .then((user: any) => {
          if (user) {
            return true;
          } else {
            return false;
          }
        })
        .catch(() => {
          return false;
        });
    }
  }

  public getUser(): Promise<any> {
    return Auth.currentUserInfo();
  }

  public getSession(): Promise<any> {
    return Auth.currentSession();
  }

  public updateUser(user: IUser): Promise<any> {
    return Auth.currentUserPoolUser().then((cognitoUser: any) => {
      return Auth.updateUserAttributes(cognitoUser, user);
    });
  }
}

One hint: You should also review your types. Setting any as a type is usually not a good practice.

  • Related