Nest.js Next.js Auth0 JWT検証

updated Oct 2, 2021created Oct 2, 2021

Nest.js

bash
yarn add passport @nestjs/passport passport-jwt jwks-rsa

ExtractJwt.fromAuthHeaderAsBearerToken()のところで、BearerTokenを扱っているようです。

jwt.strategy.ts
import { Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { ExtractJwt, Strategy } from 'passport-jwt'; import { passportJwtSecret } from 'jwks-rsa'; import * as dotenv from 'dotenv'; dotenv.config(); @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor() { super({ secretOrKeyProvider: passportJwtSecret({ cache: true, rateLimit: true, jwksRequestsPerMinute: 5, jwksUri: `${process.env.AUTH0_ISSUER_URL}.well-known/jwks.json`, }), jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), // 👈 ポイント audience: process.env.AUTH0_AUDIENCE, issuer: `${process.env.AUTH0_ISSUER_URL}`, algorithms: ['RS256'], }); } validate(payload: unknown): unknown { return payload; } }
auth.module.ts
import { Module } from '@nestjs/common'; import { PassportModule } from '@nestjs/passport'; import { JwtStrategy } from './jwt.strategy'; @Module({ imports: [PassportModule.register({ defaultStrategy: 'jwt' })], providers: [JwtStrategy,], exports: [PassportModule], }) export class AuthModule {}
users.controller.ts
import { Controller, Get, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; @Controller('users') export class UsersController { @Get('public') async test() { return '✅ Public API!' } @UseGuards(AuthGuard('jwt')) // 👈 ガード @Get('private') async private() { return '✅ Private API!' } }

Next.js

※accessTokenが無い(or違う)と、users/privateAPIは401です。

index.js
import axios from "axios"; import { useAuth0 } from "@auth0/auth0-react"; const { getAccessTokenSilently } = useAuth0(); const publicApi = async () => { try { const res = await axios.get('http://localhost:8080/users/public') console.log('✅ res', res); } catch (e) { console.log(e.message); } } const privateApi = async () => { try { const accessToken = await getAccessTokenSilently({ audience: process.env.NEXT_PUBLIC_AUTH0_AUDIENCE, scope: "read:current_user", }); console.log('✅ accessToken', accessToken); const res = await axios.get('http://localhost:8080/users/private', { headers: { Authorization: `Bearer ${accessToken}`, // 👈 accessToken を含める }, }); console.log('✅ res', res); } catch (e) { console.log(e.message); } }

実装結果

Next.js Next.js  Prisma

環境変数

Nest.js

.env
AUTH0_AUDIENCE='http://localhost:8080' AUTH0_ISSUER_URL='https://xxxxx.jp.auth0.com/'

Next.js

.env
NEXT_PUBLIC_AUTH0_DOMAIN="xxxxx.jp.auth0.com" NEXT_PUBLIC_AUTH0_CLIENT_ID="xxxxx" NEXT_PUBLIC_AUTH0_REDIRECT_URI="http://localhost:3000" NEXT_PUBLIC_AUTH0_AUDIENCE="http://localhost:8080"

ドキュメント