はじめに
本記事は表題の通り、NestJsでWebsocket.ioを使用する際、Jwt認証を行う方法について記載します。
実装方法については以下を参考にしてください。わかりやすかったです。
(推奨)handleConnectionで認証を行う
handleConnection内で認証を行います。
また、定期的にトークンの有効期限の確認も行います。
フロント側でauthにトークンを付与します。
フロント側
const socket = io('http://localhost:3001', {
auth: {
token: `Bearer ${accessToken.data.accessToken}`,
},
});
NestJs側でトークンを取得、configServiceを使用して検証を行います。
NestJS側
handleConnection(client: Socket) {
const tokenVerificationInterval = setInterval(() => {
try {
const token = client.handshake.auth.token.startsWith('Bearer ') ? client.handshake.auth.token.slice(7) : client.handshake.auth.token;
const secret = this.configService.get<string>('JWT_SECRET_KEY');
const decoded = this.jwtService.verify(token, { secret });
} catch (error) {
// トークンが無効な場合、切断する
console.log('トークンが無効または期限切れです。接続を切断します...');
client.disconnect(true);
}
}, 60000); // 例: 60秒ごとにトークンの検証を行う
client.on('disconnect', () => {
clearInterval(tokenVerificationInterval);
});
(非推奨)guardを実装して関数ごとにアクセスを制限する
@UseGuardsを使用して関数単位でアクセスを制限する方法もありますが、
関数単位での制限は可能ですが、WebSocket接続自体を防ぐことはできません。
そのため非推奨です。
以下のような形で独自のguardを実装してください
import { ExtractJwt, Strategy as BaseJwtStrategy } from 'passport-jwt';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PassportStrategy } from '@nestjs/passport';
import { JWTPayload, JWTStrategyPayload } from '../dto/jwt-payload';
import { Request } from 'express';
@Injectable()
export class JwtStrategy extends PassportStrategy(BaseJwtStrategy) {
constructor(configService: ConfigService) {
super({
// Authorization bearerからトークンを読み込む関数を返す
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: configService.get<string>('JWT_SECRET_KEY'),
passReqToCallback: true,
});
}
}
終わり
業務で実装した内容が多かったので、サンプルコードは大部分を割愛しています。
ご了承ください。
WebSocketの実装方法自体はすぐ見つかったのですが、
業務で使用するため認証が必要になり、苦労しました。
他にも問題がいくつかあり、より良い実装を模索中です。