11
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GoでJWT生成/認証を実装する。(ロジック編)

Last updated at Posted at 2022-09-24

はじめに

Webの認証で扱われるJWT。誰かが作成した認証・認可の部品を利用する事で自然に触れている。自然に触れているけど、JWTって何?どうやって作ってるの?セキュリティ周りなんでそれで大丈夫なの?って所がいまいちイメージできていなかった。今回、JWTの所を改めて勉強することにしたので、記事にして残しておきます。

JWTって何?

JWTとはJsonWebTokenの略で、ジョットと読みます。RFC7519で定義されたインターネット標準の認証方式です。公式リファレンスの抜粋では下記のように定義されています。
スクリーンショット 2022-09-24 14.34.22.png
[日本語訳]

JSON Web Token (JWT) は、コンパクトでURLセーフな表現方法です。JWT は,2 者間で転送されるクレームを表すコンパクトな URL セーフな手段である。
JWTのクレームはJSONオブジェクトとしてエンコードされ、JSONウェブ署名(JWS)構造のペイロードとして、またはJSONウェブ暗号(JWE)構造の平文として使用されます。
暗号(JWE)構造のペイロードとして使用されるJSONオブジェクトとして符号化され、クレームを電子的に署名するか、メッセージメッセージ認証コード(MAC)で署名または整合性保護され(MAC)や暗号化を可能にします。

→結局何なの??って感じですね。。。
改ざんやなりすましを検知するために、電子署名を利用してるよって位の認識で一旦OKです!!

JWTの生成、なりすまし検知方法

■JWTの生成(ログイン時)
ログイン生成時、ユーザIDとパスワードを元に認証実施。認証後、ユーザIDを秘密鍵を用いて暗号化し、トークン発行。
スクリーンショット 2022-09-24 14.56.18.png

■JWTによる認可処理(API実行時)
ログイン後、他API実行時のHeaderにJWTを付与。JWTを復号化しユーザIDを取得。ユーザIDの認可処理を実施し、そのAPI自体を叩けるかを確認。確認後、それぞれに準じた処理を実施する。
スクリーンショット 2022-09-24 15.05.31.png

ざっくり、上記のような事をやっています!!

JWTの構造

JWTはヘッダー、ペイロード、署名の3つから成り立つ。

  1. ヘッダー:トークンのタイプと署名アルゴリズムを定義
  2. ペイロード:トークン発行者、トークンの有効期限などを定義。アプリケーションで利用する値を定義する事が多いです。
  3. 署名:改ざんやなりすましを防止の電子署名を定義

では具体的にGolangの実装を元に、JWT生成と認証を実施していきましょう!!!

JWTの生成

main.go
package main

import (
	"fmt"
	"time"

	"github.com/dgrijalva/jwt-go"
)

func main() {
	// JWTに付与する構造体
	claims := jwt.MapClaims{
		"user_id": "user_id1234",
		"exp": time.Now().Add(time.Hour * 72).Unix(), // 72時間が有効期限
	}

	// ヘッダーとペイロード生成
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	// トークンに署名を付与
	accessToken, _ := token.SignedString([]byte("ACCESS_SECRET_KEY"))
	fmt.Println("accessToken:", accessToken) 
}

実行結果
~/go/src/jikken$ go run main.go
accessToken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NjQyNTk1NDUsInVzZXJfaWQiOiJ1c2VyX2lkMTIzNCJ9.CFmswwCkYu0wtPAqGkmuNovFLHSuneGLw8Qt0R7AKCE

→JWTの生成ができましたね!!では次に生成したJWTを元に認可処理を実施しましょう!!

JWTによる認可処理

main.go
package main

import (
	"fmt"

	"github.com/dgrijalva/jwt-go"
)

func main() {
	tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NjQyNTk1NDUsInVzZXJfaWQiOiJ1c2VyX2lkMTIzNCJ9.CFmswwCkYu0wtPAqGkmuNovFLHSuneGLw8Qt0R7AKCE"

	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
		}

		return []byte("ACCESS_SECRET_KEY"), nil
	})

	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		fmt.Printf("user_id: %v\n", string(claims["user_id"].(string)))
		fmt.Printf("exp: %v\n", int64(claims["exp"].(float64)))
	} else {
		fmt.Println(err)
	}
}
~/go/src/jikken$ go run main.go
user_id: user_id1234
exp: 1664259545

→できましたね!!これで完了です!!
次回はWebシステムでJWTの生成から認証処理を実施していきたいと思います!!!

11
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?