Angular NX Interceptor JWT Bearer

agnusdei·2023년 7월 5일
0
post-custom-banner

  1. Angular 에서 일반적으로 interceptor 는 프론트엔드단에서 관리합니다.

  2. pages 폴더와 같은 경로에 interceptor 폴더 생성 및 이름은 상황에 맞게 설정합니다.

import {
  CanActivate,
  ExecutionContext,
  HttpException,
  Injectable,
  UnauthorizedException,
  Logger,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { PrismaService } from '../../../prisma/prisma.service';
import { AuthUtil } from '../auth-util.service';
import { AccessTokenType } from '@namdorang/interface';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(
    private readonly authUtil: AuthUtil,
    private readonly prismaService: PrismaService
  ) {}

  canActivate(
    context: ExecutionContext
  ): boolean | Promise<boolean> | Observable<boolean> {
    const request = context.switchToHttp().getRequest(); // Http 요청을 중간에 가로 채기
    // 인증 정보 확인을 위해 변수에 할당
    const header = request.headers;
    const authorization = header.authorization; // authoriztion 이 없음!! 왜?

    Logger.log(header);

    // 국제 표준 형식 : Authorization: <type> <credentials>
    if (!authorization) {
      throw new UnauthorizedException('사용자 정보를 찾을 수 없습니다.');
    }
    // <type> 타입 이름 => Bearer
    if (!authorization.startsWith('Bearer ')) {
      throw new UnauthorizedException('사용자 정보를 찾을 수 없습니다.');
    }
    // <credentials> => random string
    const token = authorization.split(' ')[1];
    if (!token) {
      throw new UnauthorizedException('사용자 정보를 찾을 수 없습니다.');
    }

    let id;
    try {
      const payload = this.authUtil.verifyToken<AccessTokenType>(token);
      if (!payload.id) {
        throw new UnauthorizedException('유효하지 않은 토큰입니다.');
      }
      id = payload.id;
    } catch (e) {
      throw new HttpException('사용할 수 없는 토큰입니다.', 498);
    }

    const admin = this.prismaService.admin.findUnique({ where: { id } });
    if (!admin) {
      throw new UnauthorizedException('유효하지 않은 토큰입니다.');
    }

    request.user = admin; // http header 에 인증 정보를 담기

    return true;
  }
}
  1. interceptor 내부 코드 모습입니다

  2. jwt bearer 토큰을 활용하였습니다.

  3. 자세한 설명은 주석을 참고해주세요.

import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import {
  provideRouter,
  withEnabledBlockingInitialNavigation,
} from '@angular/router';
import { appRoutes } from './app.routes';
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import { HttpInterceptorImpl } from './interceptors/http-interceptor'; // interceptor
import { ToastService } from '../../../common/src';
import { NgxsModule } from '@ngxs/store'; // store
import { AdminStore } from './store/auth.store'; // store

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(appRoutes, withEnabledBlockingInitialNavigation()),
    importProvidersFrom(HttpClientModule, NgxsModule.forRoot([AdminStore])),
    { provide: HTTP_INTERCEPTORS, useClass: HttpInterceptorImpl, multi: true },
    ToastService,
  ],
};
  1. injectable 을 사용하였으니 프로젝트 app.config 에 설정을 추가합니다.
post-custom-banner

0개의 댓글