## 概要 [Task3756: Azure Functions実装(一括登録)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3756) - ユーザー一括登録用のAzure Functionを実装しました。 ## レビューポイント - 処理の流れがラフスケッチと認識通りでしょうか? - JSONファイルの内容はイメージ通りでしょうか? ## UIの変更 - なし ## 動作確認状況 - ローカルで確認 - テスト実行 実際の詳細な動作についてはdevelop環境で確認します。
131 lines
3.4 KiB
TypeScript
131 lines
3.4 KiB
TypeScript
import * as jwt from "jsonwebtoken";
|
||
// XXX: decodeがうまく使えないことがあるので応急対応 バージョン9以降だとなる?
|
||
import { decode as jwtDecode } from "jsonwebtoken";
|
||
|
||
export type VerifyError = {
|
||
reason: "ExpiredError" | "InvalidToken" | "InvalidTimeStamp" | "Unknown";
|
||
message: string;
|
||
};
|
||
|
||
export const isVerifyError = (arg: unknown): arg is VerifyError => {
|
||
const value = arg as VerifyError;
|
||
if (value.message === undefined) {
|
||
return false;
|
||
}
|
||
|
||
if (value.reason === undefined) {
|
||
return false;
|
||
}
|
||
switch (value.reason) {
|
||
case "ExpiredError":
|
||
case "InvalidTimeStamp":
|
||
case "InvalidToken":
|
||
case "Unknown":
|
||
return true;
|
||
default:
|
||
return false;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Payloadと秘密鍵を使用して署名されたJWTを生成します
|
||
* @param {T} payload payloadの型
|
||
* @param {number} expirationSeconds トークンの有効期限(秒)
|
||
* @param {string} privateKey 署名に使用する秘密鍵
|
||
* @return {string} 署名済みトークン
|
||
* @throws {Error} 秘密鍵の形式が間違っている等の理由が格納されたErrorオブジェクト
|
||
*/
|
||
export const sign = <T extends object>(
|
||
payload: T,
|
||
expirationSeconds: number,
|
||
privateKey: string
|
||
): string => {
|
||
try {
|
||
const token = jwt.sign(payload, privateKey, {
|
||
expiresIn: expirationSeconds,
|
||
algorithm: "RS256",
|
||
});
|
||
return token;
|
||
} catch (e) {
|
||
throw e;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* tokenと公開鍵を使用して検証済みJWTのpayloadを取得します
|
||
* @param {string} token JWT
|
||
* @param {string} publicKey 検証に使用する公開鍵
|
||
* @return {T | VerifyError} Payload または 検証エラーの内容を表すオブジェクト
|
||
*/
|
||
export const verify = <T extends object>(
|
||
token: string,
|
||
publicKey: string
|
||
): T | VerifyError => {
|
||
try {
|
||
const payload = jwt.verify(token, publicKey, {
|
||
algorithms: ["RS256"],
|
||
}) as T;
|
||
return payload;
|
||
} catch (e) {
|
||
if (e instanceof jwt.TokenExpiredError) {
|
||
return {
|
||
reason: "ExpiredError",
|
||
message: e.message,
|
||
};
|
||
} else if (e instanceof jwt.NotBeforeError) {
|
||
return {
|
||
reason: "InvalidTimeStamp",
|
||
message: e.message,
|
||
};
|
||
} else if (e instanceof jwt.JsonWebTokenError) {
|
||
return {
|
||
reason: "InvalidToken",
|
||
message: e.message,
|
||
};
|
||
} else {
|
||
return {
|
||
reason: "Unknown",
|
||
message: e.message,
|
||
};
|
||
}
|
||
}
|
||
};
|
||
|
||
/**
|
||
* tokenから未検証のJWTのpayloadを取得します
|
||
* @param {string} token JWT
|
||
* @return {T | VerifyError} Payload または デコードエラーの内容を表すオブジェクト
|
||
*/
|
||
export const decode = <T extends object>(token: string): T | VerifyError => {
|
||
try {
|
||
const payload = jwtDecode(token, {
|
||
json: true,
|
||
}) as T;
|
||
return payload;
|
||
} catch (e) {
|
||
if (e instanceof jwt.TokenExpiredError) {
|
||
return {
|
||
reason: "ExpiredError",
|
||
message: e.message,
|
||
};
|
||
} else if (e instanceof jwt.NotBeforeError) {
|
||
return {
|
||
reason: "InvalidTimeStamp",
|
||
message: e.message,
|
||
};
|
||
} else if (e instanceof jwt.JsonWebTokenError) {
|
||
return {
|
||
reason: "InvalidToken",
|
||
message: e.message,
|
||
};
|
||
} else {
|
||
return {
|
||
reason: "Unknown",
|
||
message: e.message,
|
||
};
|
||
}
|
||
}
|
||
};
|
||
|
||
export const getJwtKey = (key: string): string => key.replace(/\\n/g, "\n");
|