makabe.t d6a47932e7 Merged PR 786: Azure Functions実装(一括登録)
## 概要
[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環境で確認します。
2024-03-06 01:48:02 +00:00

131 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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");