Issue
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
Solution
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.
Answered By - Fabian Strathaus
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.