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.