JWTのペイロードにカスタムクレームを追加する方法をやさしく解説|初心者でもわかるJWT クレームの基本
新人
「JWTのペイロードって何ですか?クレームっていうのもよく分かりません…」
先輩
「JWTは3つの部分に分かれていて、ペイロードはその中でもユーザー情報などが入る部分だよ。クレームっていうのは、その情報の種類のことなんだ。」
新人
「じゃあカスタムクレームっていうのは、自分で好きな情報を入れられるってことですか?」
先輩
「その通り。部署名やユーザーIDなど、必要な情報を追加できるよ。今回はそのやり方をじっくり解説していくね!」
1. JWTのペイロードとは?
JWT(JSON Web Token)は、トークン形式の一種で、ヘッダー・ペイロード・署名の3つの部分から構成されます。この中で「ペイロード」は、ユーザー情報や有効期限などを記述する部分であり、サーバー側でトークンの中身を解析することでユーザー認証や権限処理を行うことができます。
JWT ペイロード クレームというキーワードは検索でもよく使われるため、JWTの内部構造をしっかり理解しておくことが大切です。
例えば、次のようなJWTをBase64デコードすると、以下のような構造になります:
{
"sub": "user01",
"exp": 1723456790
}
この例では、「sub」がユーザー名(サブジェクト)、「exp」がトークンの有効期限を表しています。これらの要素がクレームと呼ばれる情報のかたまりです。つまり、JWTのペイロードとは「ユーザーに関する情報が詰め込まれた部分」と理解するとよいでしょう。
このペイロードに情報を追加することで、アプリケーション側でユーザーの状態をトークンのみで安全に扱うことが可能になります。
2. クレームとは何か?
クレーム(Claim)とは、JWTトークンの中に含まれる「属性情報」のことを指します。クレームには大きく分けて2つの種類があります。
- 標準クレーム:
sub(ユーザー識別子)、exp(有効期限)、iat(発行時刻)など、あらかじめ定義されているクレーム - カスタムクレーム:アプリケーションごとに独自に追加できる情報(例:部署名、ロール、電話番号など)
たとえば、ログインしたユーザーがどの部署に所属しているかをAPI側で知りたい場合、トークンに「department」などのカスタムクレームを追加すれば、毎回DBに問い合わせる必要がなくなります。
実際にJavaでJWTにカスタムクレームを追加するコードを見てみましょう。
public String generateToken(String username) {
Map<String, Object> claims = new HashMap<>();
claims.put("department", "sales");
claims.put("role", "admin");
return Jwts.builder()
.setClaims(claims)
.setSubject(username)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60))
.signWith(SignatureAlgorithm.HS256, "secret-key")
.compact();
}
このようにしてトークンを発行すると、ペイロードには次のような形で情報が含まれます:
{
"department": "sales",
"role": "admin",
"sub": "user01",
"iat": 1723453200,
"exp": 1723456800
}
このとき注意しておきたいのが、「セキュリティに影響を与える重要な情報はトークンに含めない」という点です。JWTのペイロードはBase64でエンコードされているだけなので、誰でも中身を見ることができます。そのため、パスワードや機密情報などを含めるのはNGです。
カスタムクレームの活用は、Spring Security JWT カスタムクレームの実装時によく使われる手法です。ユーザーの権限管理や画面表示の切り替えなど、多くの場面で役立ちます。
次回の記事では、このようなカスタムクレームを実際にどのようにJavaコードで設定し、トークンに埋め込んでいくのかをさらに詳しく見ていきましょう。
3. カスタムクレームをJWTに追加する方法(Javaコード例)
それでは、実際にJavaコードでJWT カスタムクレーム 追加方法を見ていきましょう。ここでは、Spring Securityをベースに、JWTを発行するメソッドをGradle環境で構築したプロジェクト内で実装していきます。
以下の例では、ユーザー名だけでなく、「role(ロール)」や「department(所属部署)」といった独自のカスタムクレームを含めたトークンを生成します。
public String generateToken(String username) {
Map<String, Object> claims = new HashMap<>();
claims.put("role", "user");
claims.put("department", "marketing");
return Jwts.builder()
.setClaims(claims)
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 30)) // 30分
.signWith(SignatureAlgorithm.HS256, "my-secret-key")
.compact();
}
このようにsetClaims()を使って、Mapに格納したクレームをトークンに含めることができます。setSubject()にはユーザー名を指定し、署名にはsignWith()でアルゴリズムと秘密鍵を使ってトークンの整合性を保ちます。
このトークンを生成する処理は、認証成功時のサービスクラスなどに組み込むのが一般的です。これでアプリケーションが発行するJWTに、独自の情報を埋め込むことができるようになります。
4. カスタムクレームを読み取る方法(トークンのデコードと取り出し)
JWTにカスタムクレームを追加できたら、次はトークンを受け取る側でその情報をどうやって取得するかが重要になります。これはJWT クレーム 読み取りの基本です。
以下のコードは、リクエストに含まれたトークンを解析し、クレームの内容を取り出すサンプルです。
public Claims extractClaims(String token) {
return Jwts.parser()
.setSigningKey("my-secret-key")
.parseClaimsJws(token)
.getBody();
}
parseClaimsJws()を使うことで、トークンの整合性を確認したうえで、ペイロード部分(クレーム)を安全に取り出すことができます。
たとえば、取り出したClaimsから特定のカスタムクレームを取得するには、以下のようにします。
Claims claims = extractClaims(token);
String role = claims.get("role", String.class);
String department = claims.get("department", String.class);
このようにすれば、トークンに埋め込まれていたカスタム情報を自由に活用できるようになります。画面表示の切り替えやアクセス制御に使うことも可能です。
重要なのは、トークンを使うことでセッションレスに認証情報を管理できるという点です。データベースに毎回アクセスしなくても、トークン内のクレームを利用することで、効率的なユーザー管理が実現できます。
5. セキュリティ上の注意点(入れてはいけない情報の例)
JWTのペイロードに自由に情報を入れられるからといって、何でも詰め込んでいいわけではありません。JWT セキュリティ 注意点として、以下のような情報は絶対に含めてはいけません。
- パスワード:暗号化されていない状態で含めるのは危険
- 個人情報:名前・メールアドレス・電話番号など
- 銀行口座番号やクレジットカード情報:漏洩リスクが非常に高い
JWTのペイロードはBase64エンコードされているだけであり、簡単にデコードして中身を見ることができます。そのため、「見られても困らない情報」のみに限定することが重要です。
また、秘密鍵の管理にも十分な注意が必要です。トークンの署名に使う秘密鍵(secret-key)が漏洩すれば、第三者が不正なトークンを生成してしまう恐れがあります。
以下は安全にJWTを扱うためのベストプラクティスです:
- 秘密鍵は
application.propertiesやapplication.ymlなど外部設定に分離 - 有効期限は短めに設定する(例:30分以内)
- 必要最小限の情報だけをクレームに含める
さらに、JWTを使用する場合は、トークンが改ざんされていないかどうかを検証するために、署名の整合性チェックを常に行うことも重要です。
たとえば、次のようなトークンの検証処理を認証フィルターに組み込むと、安全性が高まります。
try {
Claims claims = Jwts.parser()
.setSigningKey("my-secret-key")
.parseClaimsJws(token)
.getBody();
// 有効なトークンの場合はこのまま処理を継続
} catch (ExpiredJwtException e) {
// トークンの有効期限切れ
} catch (JwtException e) {
// トークンの不正など
}
このように、JWTの仕組みを正しく理解したうえで、カスタムクレームの取り扱いにも細心の注意を払うことが、セキュアなアプリケーション開発には欠かせません。
6. よくあるエラーとその対処法(クレームが取り出せない、デコード失敗など)
JWTを使って開発していると、JWT クレーム エラー 対処に関する問題に直面することがあります。ここでは、初心者が特につまずきやすい代表的なエラーとその解決方法を紹介します。
① クレームが取り出せない
トークンは正しく作成されているのに、クレームがnullになる場合は以下の点を確認してください。
- クレーム名のスペルミス
- 型指定の不一致(StringなのにIntegerで取得しようとしている)
- トークンが破損している
クレームを取り出すときは、次のように正しい型とキーを指定しましょう。
Claims claims = extractClaims(token);
String department = claims.get("department", String.class);
② トークンのデコード失敗
デコードエラーが発生する原因は、トークンが改ざんされていたり、署名鍵が一致しない場合です。また、有効期限切れのトークンをパースしようとするとExpiredJwtExceptionが発生します。
対処法として、try-catchでしっかり例外処理を行い、原因ごとに適切な対応をしましょう。
try {
Claims claims = extractClaims(token);
// 正常にクレーム取得
} catch (ExpiredJwtException e) {
// 有効期限切れ
} catch (SignatureException e) {
// 署名不一致
} catch (JwtException e) {
// その他の問題
}
こうした処理を加えることで、予期しないエラーが発生しても、ユーザーに分かりやすいエラーメッセージを表示できます。
7. Spring Securityと連携する際の活用例(ロール・部署情報などの活用)
Spring Security カスタムクレームの活用例として、認証フィルターでトークンを検証し、その中のクレームからユーザー情報を取得してセキュリティコンテキストに設定する方法があります。
以下は、フィルターの中でトークンからユーザー名やロールを取り出し、認証オブジェクトを作成する例です。
String token = getTokenFromRequest(request);
Claims claims = extractClaims(token);
String username = claims.getSubject();
String role = claims.get("role", String.class);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(username, null,
Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role)));
SecurityContextHolder.getContext().setAuthentication(authentication);
このように、JWTに埋め込んだカスタムクレームを活用することで、リクエストごとにデータベースアクセスをしなくても、ユーザーの権限や所属情報をもとに処理を制御できます。
例えば「部署ごとの管理画面を出し分けたい」といった要件にも対応しやすくなります。
また、@Controller側では、認証情報を使ってロールに応じた画面遷移や処理分岐を行うことも可能です。
8. 初心者におすすめの学習手順(JWTとSpring Securityの理解ステップ)
JWTやSpring Securityの学習を始めたばかりの初心者にとって、学ぶべき内容が多すぎて混乱することがあります。そこで、効率的な学習ステップを紹介します。
- ステップ①:JWTの基本構造を理解する
JWTが3つの部分(ヘッダー・ペイロード・署名)に分かれていることを知ることから始めましょう。 - ステップ②:JWTの生成と検証を試す
簡単なスタンドアロンのJavaプロジェクトで、トークンを生成・パースしてみましょう。 - ステップ③:Spring Boot + Spring Securityのプロジェクトを作る
Gradle環境でSpring Securityのサンプル認証処理を構築して、仕組みを体感してください。 - ステップ④:JWTとSpring Securityを組み合わせる
カスタムフィルターを追加して、トークンを使った認証の流れを構築しましょう。 - ステップ⑤:クレームの活用に挑戦する
部署情報やロールなどをJWTに埋め込み、画面の制御や処理の切り替えに活用してみましょう。
このように段階を踏んで学習していくことで、ただコードを書くのではなく、「なぜその処理が必要なのか」が理解できるようになります。
また、JWT クレーム 学習を通じて、セキュアでスケーラブルな認証システムを作れるようになります。
初めは難しく感じるかもしれませんが、一つひとつを丁寧に習得していくことで、着実にスキルアップできるので安心してください。