I am doing an authentication with saml in nestjs I am using the passport-saml package I am directing the page to the microsoft login correctly but in the callback route I do not get the profile data, what I want is to make the person authenticate with saml and that after that a token bearer is generated in the system, so far as I mentioned before I have not been able to obtain the data of the user who starts the session.
auth.module.ts
import { AuthController } from './auth.controller';
import { Saml2Strategy } from './strategies/saml.strategy';
import { Module } from '#nestjs/common';
import { AuthService } from './auth.service';
#Module({
controllers: [AuthController],
providers: [AuthService, Saml2Strategy],
})
export class AuthModule {}
controller the route is get('saml'), It is addressing correctly, but when returning to the callback url I cannot obtain the data of the person.
auth.controller.ts
import { Saml2Strategy } from './strategies/saml.strategy';
import {
Controller,
Get,
Post,
UseGuards,
Res,
Req,
Request,
Body,
} from '#nestjs/common';
import { AuthGuard } from '#nestjs/passport';
import { ApiTags } from '#nestjs/swagger';
const passport = require('passport');
const SamlStrategy = require('passport-saml').Strategy;
import { ConfigSaml } from './../user/controllers/config';
const fs = require('fs');
#ApiTags('Auth')
#Controller('auth')
export class AuthController {
public config: ConfigSaml;
public userData: any;
constructor() {
this.config = new ConfigSaml();
}
#Get('saml')
#UseGuards(AuthGuard('saml'))
samlLogin() {
}
#Post('/callback')
async callback(#Request() req, #Body() body: any) {
if (req.isAuthenticated()) {
console.log('autenticado');
}
}
}
saml.strategy.ts
import { Injectable } from '#nestjs/common';
import { PassportStrategy } from '#nestjs/passport';
import { passport } from 'passport';
var SamlStrategy = require('passport-saml').Strategy;
const fs = require('fs');
#Injectable()
export class Saml2Strategy extends PassportStrategy(SamlStrategy, 'saml') {
constructor() {
super({
entryPoint: process.env.SAML_ENTRY_POINT,
issuer: process.env.SAML_ISSUER,
callbackUrl: process.env.SAML_CALLBACK_URL,
cert: fs.readFileSync(
process.cwd() +
'/src/modules/auth/strategies/' +
process.env.SAML_CERT ||
process.cwd() + '/src/modules/auth/strategies/certificate.pem',
'utf-8',
),
function(profile, done) {
console.log('profile in strategy', profile);
return done(null, {
id: profile.nameID,
email:
profile[
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'
],
displayName:
profile['http://schemas.microsoft.com/identity/claims/displayname'],
firstName:
profile[
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname'
],
lastName:
profile[
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname'
],
});
},
});
}
}
It seems like an old query...
and I guess over here you are trying to get the SAML response as a Profile object, which is provided by the passport-saml strategy
So to retrieve the SAML response as a Profile object you need to set the same guard in the callback API '#Post('/callback')' as well, which you have used in the '#Get('saml')' API which is
#UseGuards(AuthGuard('saml'))
So your updated code block will be:
import { Saml2Strategy } from './strategies/saml.strategy';
import {
Controller,
Get,
Post,
UseGuards,
Res,
Req,
Request,
Body,
} from '#nestjs/common';
import { AuthGuard } from '#nestjs/passport';
import { ApiTags } from '#nestjs/swagger';
const passport = require('passport');
const SamlStrategy = require('passport-saml').Strategy;
import { ConfigSaml } from './../user/controllers/config';
const fs = require('fs');
#ApiTags('Auth')
#Controller('auth')
export class AuthController {
public config: ConfigSaml;
public userData: any;
constructor() {
this.config = new ConfigSaml();
}
#Get('saml')
#UseGuards(AuthGuard('saml'))
samlLogin() {
}
#Post('/callback')
#UseGuards(AuthGuard('saml'))
async callback(#Request() req, #Body() body: any) {
if (req.isAuthenticated()) {
console.log('autenticado');
}
}
}
Related
I am a new coder with nestjs, I want to use passport-jwt , nestjs/passport and firebase to build my app's authetication part, below are my codes. But I just got http 401 response, how can i fix it ?
here is my strategy:
import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '#nestjs/passport';
import { Injectable } from '#nestjs/common';
import { getAuth } from 'firebase-admin/auth';
#Injectable()
export class FirebaseStrategy extends PassportStrategy(Strategy, 'firebase') {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKeyProvider: async (request, rawJwtToken, done) => {
try {
const decodedToken = await getAuth().verifyIdToken(rawJwtToken);
done(null, decodedToken);
} catch (error) {
done(error);
}
},
});
}
async validate(payload: any) {
console.log('validate');
return payload;
}
}
here is my guard:
import { Injectable } from '#nestjs/common';
import { AuthGuard } from '#nestjs/passport';
#Injectable()
export class FirebaseAuthGuard extends AuthGuard('firebase') {}
here is my auth.module.ts:
import { Module } from '#nestjs/common';
import { AuthService } from './auth.service';
import { UsersModule } from '../users/users.module';
import { PassportModule } from '#nestjs/passport';
import { JwtModule } from '#nestjs/jwt';
import { FirebaseStrategy } from './firebase.stragety';
import { AuthController } from './auth.controller';
#Module({
controllers: [AuthController],
imports: [UsersModule, PassportModule, JwtModule.register({})],
providers: [AuthService, FirebaseStrategy],
exports: [AuthService],
})
export class AuthModule {}
and here is my controller:
import { Controller, Get, Request, UseGuards } from '#nestjs/common';
import { AuthService } from './auth.service';
import { FirebaseAuthGuard } from './firebase.guard';
#Controller('auth')
export class AuthController {
constructor(private authService: AuthService) {}
#UseGuards(FirebaseAuthGuard)
#Get('login')
async logIn(#Request() req) {
return 'login';
}
}
I just found my validate method in FirebaseStrategy not invoked, it should be invoked everytime when secretOrKeyProvider verified jwt in http header, isn't it ?
If you're getting a 401 with no call of the validate method of your JwtStrategy that means that for some reason passport is reading the JWT you send as invalid. To find the specific reason for it you can modify your FirebaseAuthGuard to have the following handleRequest method, which will log out extra details
handleRequest(err, user, info, context, status) {
console.log({ err, user, info, context, status });
return super.handleRequest(err, user, info, context, status);
}
As mentioned, this will print out what error or info passport is reading and throwing for, and will allow you to properly adjust your JWT/know to refresh it/change it because of invalid signature/whatever else.
I need help with processing after authentication using Nest.js
here do I pass the failureRedirect option for passport-local when using Nest.js for authentication?
Without Nest.js
app.post('/login', passport.authenticate('local', {
//Passing options here.
successRedirect: '/',
failureRedirect: '/login'
}));
My code is. (with Nest.js)
local.strategy.ts
import { Injectable, UnauthorizedException } from "#nestjs/common";
import { PassportStrategy } from "#nestjs/passport";
import { Strategy } from "passport-local";
import { AuthService } from "./auth.service";
#Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor(private authService: AuthService) {
super({
//I tried passing the option here. but failed.
})
}
async validate(username: string, password: string): Promise<string | null> {
const user = this.authService.validate(username, password);
if (!user) {
throw new UnauthorizedException();
}
return user;
}
}
local.guard.ts
import { Injectable } from "#nestjs/common";
import { AuthGuard } from "#nestjs/passport";
#Injectable
export class LocalAuthGuard extends AuthGuard('local') {}
auth.controller.ts
import { Controller, Get, Post, Render, UseGuards } from "#nestjs/common";
import { LocalAuthGuard } from "./local.guard";
#Controller()
export class AuthController {
#Get("/login")
#Render("login")
getLogin() {}
//Redirect to '/login' when authentication failed.
#UseGuards(LocalAuthGuard)
#Post("/login")
postLogin() {}
}
auth.module.ts
import { Module } from "#nestjs/common";
import { PassportModule } from "#nestjs/passport";
import { AuthController } from "./auth.controller";
import { AuthService } from "./auth.service";
import { LocalStrategy } from "./local.strategy";
import { LocalAuthGuard } from "./local.guard";
#Module({
controllers: [AuthController],
imports: [PassportModule],
providers: [AuthService, LocalStrategy, LocalAuthGuard]
})
export class AuthModule {}
I tried adding code to AuthController#postLogin to redirect on login failure, but the code seems to run only on successful login.
I would like to redirect to the login page again in case of login failure with the failureRedirect option of passport-local.
I found a workaround since using the passport options sadly didn't work:
#Injectable()
export class LocalAuthGuard extends AuthGuard('local') {
getAuthenticateOptions(context: ExecutionContext): IAuthModuleOptions {
return {
successReturnToOrRedirect: '/',
failureRedirect: '/login',
};
}
}
Instead I created a Nestjs Filter to catch an exception containing a redirect URL.
redirecting.exception.ts
export class RedirectingException {
constructor(public url: string) {}
}
redirecting-exception.filter.ts
import { ArgumentsHost, Catch, ExceptionFilter } from '#nestjs/common';
import { Response } from 'express';
import { RedirectingException } from './redirecting.exception';
#Catch(RedirectingException)
export class RedirectingExceptionFilter implements ExceptionFilter {
catch(exception: RedirectingException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
response.redirect(exception.url);
}
}
In my validate method I'm throwing the RedirectingException with the correct error msg, e.g.
throw new RedirectingException('/login?error="User not found"');
And the controller handles the rest of the redirecting and passes the error to the view, so it can be displayed:
#Get('/login')
#Render('login.pug')
#Public()
async login(#Query() query) {
return { error: query.error };
}
#Post('/login')
#Public()
#UseGuards(LocalAuthGuard)
#Redirect('/')
async doLogin() {}
I'd rather use the passport functionality including the failureFlash, but I couldn't get it to work.
here is my auth.controller.ts
import { Body, Controller, Get, Post, Req, Res, UnauthorizedException, ValidationPipe } from '#nestjs/common';
import { ApiBadRequestResponse, ApiCreatedResponse, ApiForbiddenResponse, ApiOkResponse, ApiTags, ApiUnauthorizedResponse } from '#nestjs/swagger';
import { User } from 'src/interfaces/user.interface';
import { AuthService } from './auth.service';
import { AuthCredentials } from './dto/auth-credential.dto';
import { Response,Request } from 'express';
import { JwtService } from '#nestjs/jwt';
#ApiTags('auth')
#Controller('auth')
export class AuthController {
constructor(
private authService: AuthService,
private jwtService: JwtService
){}
#Post('/signup')
#ApiCreatedResponse({description: 'this response has created successfully'})
#ApiForbiddenResponse({description: 'Forbidden'})
signUp(#Body(ValidationPipe) authCredentials:AuthCredentials):Promise<User> {
return this.authService.signUp(authCredentials);
}
#Post('/signin')
#ApiOkResponse({description:'The resource has been successfully returned'})
#ApiForbiddenResponse({description:'Invalid credintials'})
async signin(#Body(ValidationPipe) authCredentials:AuthCredentials,#Res() response: Response):Promise<{accessToken:string}> {
const token = await this.authService.signIn(authCredentials);
response
.cookie('access_token', token, {
httpOnly: true,
domain: 'localhost', // your domain here!
expires: new Date(Date.now() + 1000 * 60 * 60 * 24),
// expires: new Date(Date.now() + 60000 ),
})
.send(token);
return token;
}
#Get('/cookies')
findAll(#Req() request: Request) {
console.log(request.cookies['access_token'].accessToken);
// or
// "request.cookies['cookieKey']"
// or
// console.log(request.signedCookies);
}
// to verify the user's token
#Get('/user')
#ApiOkResponse({description:'User varified Successfully'})
#ApiUnauthorizedResponse({description:'Unauthorised User'})
async user(#Req() request: Request) {
try{
const cookies = request.cookies['access_token']
const cookie = cookies.accessToken
const data = await this.jwtService.verifyAsync(cookie)
if(!data) {
throw new UnauthorizedException()
}
const user = await this.authService.findOne(data.username)
return user;
}catch(e){throw new UnauthorizedException()}
}
// to logout by delelting the token
#ApiOkResponse({description:'User varified Successfully'})
#ApiBadRequestResponse({description:'login failed'})
#Post('logout')
async logout(#Res({passthrough: true}) response: Response) {
response.clearCookie('access_token');
return {
message: 'Logged out successfully'
}
}
}
here is my auth.module.ts
import { Module } from '#nestjs/common';
import { APP_GUARD } from '#nestjs/core';
import { JwtModule } from '#nestjs/jwt';
import { PassportModule } from '#nestjs/passport';
import { DatabaseModule } from 'src/database/database.module';
import { AuthController } from './auth.controller';
import { authProviders } from './auth.provider';
import { AuthService } from './auth.service';
import { AuthStrategy } from './auth.strategy';
import { JwtStrategy } from './jwt.strategy';
import { RolesGuard } from './roles.guard';
import { UserRepository } from './user.repository';
#Module({
imports: [
PassportModule.register({defaultStrategy:'jwt'}),
JwtModule.register({
secret: 'abcdefghijklmnop',
signOptions:{
expiresIn: 60000,
}
}),
DatabaseModule],
controllers: [AuthController],
providers: [
...authProviders,
AuthService,
UserRepository,
JwtStrategy,
AuthStrategy,
{
provide: APP_GUARD,
useClass: RolesGuard,
},
// RolesGuard
],
exports: [
JwtStrategy,
PassportModule
]
})
export class AuthModule {}
here is jwt.strategy.ts
import { PassportStrategy } from "#nestjs/passport";
import { Strategy,ExtractJwt } from "passport-jwt"
import { Inject, Injectable, UnauthorizedException } from "#nestjs/common";
import { JwtPayload } from "../interfaces/jwt-payload.interface";
import { Model } from "mongoose";
import { User } from "src/interfaces/user.interface";
#Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(
#Inject('USER_MODEL')
private authModel: Model<User>,
){
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken('Bearer'),
secretOrKey: 'abcdefghijklmnop',
})
}
async validate(payload: JwtPayload):Promise<User>{
const { username } = payload ;
const user = await this.authModel.findOne({ username }) ;
if(!user){
throw new UnauthorizedException()
}
return user
}
// async validate(payload: any) {
// return { ...payload.user };
// }
}
here is my user.repository.ts
import { BadRequestException, Inject, Injectable, UnauthorizedException } from "#nestjs/common";
import { Model } from "mongoose";
import { User } from "src/interfaces/user.interface";
import { AuthCredentials } from "./dto/auth-credential.dto";
var bcrypt = require('bcryptjs');
#Injectable()
export class UserRepository{
constructor(
#Inject('USER_MODEL')
private authModel: Model<User>
){}
async validateUser(authCredentials):Promise<boolean> {
const username = authCredentials.username
const userExist = await this.authModel.findOne({ username})
if(userExist === null) {return true}
else {return false}
}
async validateUserPassword(authCredentials:AuthCredentials): Promise<string> {
const { username, password } = authCredentials;
const user = await this.authModel.findOne({ username})
if (user === null) {
throw new UnauthorizedException('Invalid credintials')
}else {
const isMatch = await bcrypt.compare(password, user.password)
if (isMatch) {
return user.username
}else {throw new BadRequestException('Invalid credintials')}
}
}
}
this is auth module. I've applicant, application and some other modules too which I've to authenticate. These are working fine in swagger but I've a react frontend app, Which also working partially, means it only storing the token in the cookie but whenever trying to get or access other modules they responses as 401(Unauthorised)
I have a user service that handles registration, login and some other functions. I have been working on the application for sometime now with over 10 modules. But I noticed each time I injected another service and I try to consume any endpoint I get this error "Unknown authentication strategy "jwt". Error on swagger is:-
Internal Server Error
Response body
{
"statusCode": 500,
"message": "Internal server error"
}
Once I remove the injected service from the user module, everything is fine again. I have been trying to fix this because I need to use this service inside the user module.
This is the jwt.Strategy.ts
import { Injectable, HttpException, HttpStatus } from "#nestjs/common";
import { PassportStrategy } from '#nestjs/passport';
import { Strategy, ExtractJwt, VerifiedCallback } from "passport-jwt";
import { AuthService } from './auth.service';
#Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(private authService: AuthService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: process.env.SECRETKEY
});
}
async validate(payload: any, done: VerifiedCallback) {
const user = await this.authService.validateUser(payload);
try {
if (user) {
//return user;
return done(null, user, payload.iat)
} else if (user == null) {
const Terminal = await this.authService.validatePos(payload);
return done(null, Terminal, payload.iat)
}
else {
return done(
//throw new UnauthorizedException();
new HttpException('Unauthorised access', HttpStatus.UNAUTHORIZED),
false,
);
}
} catch (error) {
return error;
}
}
}
This is the AuthModule
import { Module } from '#nestjs/common';
import { AuthService } from './auth.service';
import { UserService } from '../user/user.service';
import { UserSchema } from '../user/user.schema';
import { MongooseModule } from '#nestjs/mongoose';
import { JwtStrategy } from './jwt.strategy';
import { ActivityLogService } from '../activity-log/activity-log.service';
import { ApiKeyStrategy } from './apiKey.strategy';
import { PassportModule } from "#nestjs/passport";
#Module({
imports: [MongooseModule.forFeature([{ name: 'User', schema: UserSchema }]),
PassportModule.register({
secret: "mysec"
}),
ActivityLogService],
providers: [AuthService, UserService, JwtStrategy, ApiKeyStrategy, ActivityLogService],
exports: [AuthService],
controllers: []
})
export class AuthModule { }
This is the api.strategy.ts
import { HeaderAPIKeyStrategy } from 'passport-headerapikey';
import { PassportStrategy } from '#nestjs/passport';
import { Injectable, HttpException, HttpStatus } from '#nestjs/common';
import { AuthService } from './auth.service';
#Injectable()
export class ApiKeyStrategy extends PassportStrategy(HeaderAPIKeyStrategy) {
constructor(private authService: AuthService) {
super({
header: 'api_key',
prefix: ''
}, true,
(apikey: string, done: any, req: any, next: () => void) => {
const checkKey = this.authService.validateApiKey(apikey);
if (!checkKey) {
return done(
new HttpException('Unauthorized access, verify the token is correct', HttpStatus.UNAUTHORIZED),
false,
);
}
return done(null, true, next);
});
}
}
This is the authService
import { Injectable } from '#nestjs/common';
import { sign } from 'jsonwebtoken';
import { UserService } from '../user/user.service';
import { TerminalService } from '../terminal/terminal.service';
import { InjectModel } from '#nestjs/mongoose';
import { Model } from 'mongoose';
import { Terminal } from '../terminal/interfaces/terminal.interface';
#Injectable()
export class AuthService {
constructor(private userService: UserService, #InjectModel('Terminal') private terminalModel: Model<Terminal>,) { }
//generate token for user
async signPayLoad(payload: any) {
return sign(payload, process.env.SECRETKEY, { expiresIn: '1h' });
}
//find user with payload
async validateUser(payload: any) {
const returnuser = await this.userService.findByPayLoad(payload);
return returnuser;
}
//generate token for Posy
async signPosPayLoad(payload: any) {
return sign(payload, process.env.SECRETKEY, { expiresIn: '24h' });
}
//find terminal with payload
async validatePos(payload: any) {
const { terminalId } = payload;
const terminal = await this.terminalModel.findById(terminalId);
return terminal;
}
validateApiKey(apiKey: string) {
const keys = process.env.API_KEYS;
const apiKeys = keys.split(',');
return apiKeys.find(key => apiKey === key);
}
}
This is the user service
import { Injectable, HttpException, HttpStatus, Inject } from '#nestjs/common';
import { User } from './interfaces/user.interface';
import { Model } from 'mongoose';
import { InjectModel } from '#nestjs/mongoose';
import { LoginUserDto } from './login-user.dto';
import { ActivityLogService } from '../activity-log/activity-log.service';
import { UpdateUserDTO } from './dtos/update_user.dto';
#Injectable()
export class UserService {
constructor(#InjectModel('User') private userModel: Model<User>,
private activityLogService: ActivityLogService,
) { }
//Login user
private users = [
{
"userId": 1,
"name": "John Doe",
"username": "john",
"password": "john123"
},
]
async login(loginDTO: LoginUserDto) {
const { email, password } = loginDTO;
return await this.users.find(users => users.username == email)
}
async findByPayLoad(payload: any) {
const { userId } = payload;
return await this.userModel.findById(userId)
}
async getAllUser() {
return this.users;
}
}
I cant figure out what I am doing wrong
Besides the code being difficult to manipulate and determine what's happening, services being in places they shouldn't and re-instantiations of services all over the place, the culprit as to why you are getting the error is simply because you never register the PassportModule from #nestjs/passport
EDIT 1/7/2017
Coming back to this answer about a year and a half later, it looks like the real issue is the use of a REQUEST scoped provider in the strategy. The nest docs explicitly mention this can't be done directly but also have a workaround for it.
I have a token based authorization. Authorization happens well there are no errors. But now need to somehow display the data of an authorized user. Please tell me how to properly implement the profile on the client (Angular 6)?
I have this server:
controller:
const db = require('../config/db.config.js')
const User = db.user
const errorHandler = require('../utils/errorHandler')
module.exports.getProfile = async function(req, res) {
try {
await User.findOne({ id: req.user.id}, (user) => {
res.json({
success: true,
user: user,
message: "Successful"
})
})
}catch(e) {
errorHandler(req, e)
}
}
routes:
const express = require('express')
const router = express.Router()
const controller = require('../controllers/user')
const passport = require('passport')
router.get('/profile', passport.authenticate('jwt', {session: false}), controller.getProfile)
module.exports = router
passport:
const JwtStrategy = require('passport-jwt').Strategy
const ExtractJwt = require('passport-jwt').ExtractJwt
const db = require('../config/db.config.js')
const User = db.user
const options = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: process.env.SECRET_OR_KEY
}
module.exports = passport => {
passport.use(
new JwtStrategy(options, async (payload, done) => {
try {
const user = await User.findById(payload.userId).toJSON('username id')
if (user) {
done(null, user)
} else {
done(null, false)
}
} catch(e) {
console.log(e)
}
})
)
}
And here is a part of the client:
app-components:
import { Component, OnInit } from '#angular/core';
import { AuthService } from './shared/services/auth.service';
#Component({
selector: 'app-root',
template: '<router-outlet></router-outlet>'
})
export class AppComponent implements OnInit {
constructor(private auth: AuthService) {
}
ngOnInit() {
const potentialToken = localStorage.getItem('auth-token')
if (potentialToken !== null) {
this.auth.setToken(potentialToken)
}
}
}
auth.service:
import { Injectable, Optional } from "#angular/core";
import { HttpClient } from "#angular/common/http";
import { Router, ActivatedRoute } from "#angular/router";
import { Observable } from "rxjs";
import { tap } from "rxjs/operators";
import { User } from "../interfaces";
#Injectable({
providedIn: 'root'
})
export class AuthService {
private token = null;
constructor(
private http: HttpClient,
#Optional() private _activatedRoute: ActivatedRoute,
#Optional() private _router: Router
) {}
login(user: User): Observable<{token: string}> {
return this.http.post<{token: string}>('/api/auth/login', user)
.pipe(
tap(
({token}) => {
localStorage.setItem('auth-token', token)
this.setToken(token)
}
)
)
}
setToken(token: string) {
this.token = token
}
getToken(): string {
return this.token
}
isAuthenticated(): boolean {
return !!this.token
}
logout() {
this.setToken(null)
localStorage.clear()
}
}
token.interceptor.ts:
import { Injectable } from "#angular/core";
import { AuthService } from "../services/auth.service";
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from "#angular/common/http";
import { Observable, throwError } from "rxjs";
import { catchError } from "rxjs/operators";
import { Router } from "#angular/router";
#Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(private auth: AuthService, private router: Router){
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.auth.isAuthenticated()) {
req = req.clone({
setHeaders: {
Authorization: this.auth.getToken()
}
})
}
return next.handle(req).pipe(
catchError(
(error: HttpErrorResponse) => this.handleAuthError(error)
)
)
}
private handleAuthError(error: HttpErrorResponse): Observable<any> {
if (error.status === 401) {
this.router.navigate(['/sign_in']), {
queryParams: {
sessionFailed: true
}
}
}
return throwError(error)
}
}
What need to implement on the client to display user data. Tell me please, I'm new.
You just need to create a Service class called UserService which will keep the information related to logged in user.
Whenever login action is performed successfully, just get the user details and fill it in UserService class.
user.service.ts
export class UserService {
private currentUser$: new BehaviorSubject<User>; //<-- check your user type
constructor(private http: Http) { }
getCurrentUser() {
this.currentUser$;
}
setCurrentUser(user:User){
this.currentUser$.next(user); //update the current user
}
}
This service class will give the Observable and you can use it any component or service class.