0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Golang EchoフレームワークでJWT認証を実装する方法

Last updated at Posted at 2024-11-03

初心者向けガイド:Golang EchoフレームワークでJWT認証を実装する方法(Mac環境)

ウェブアプリケーションの開発において、ユーザー認証は重要な要素の一つです。
特に、セキュアな認証システムを構築するために、JSON Web Tokens(JWT)は広く利用されています。
本記事では、Golang(Go)言語とEchoフレームワークを使用して、JWT認証を実装する方法を初心者にもわかりやすく解説します。
Mac環境での検証を前提としています。

目次

  1. プロジェクトのセットアップ
  2. 主要なファイルの解説
  3. サーバーの起動とテスト
  4. まとめ

プロジェクトのセットアップ

まず、Golangと必要なパッケージをインストールします。
以下の手順に従ってプロジェクトをセットアップしましょう。

1. Goのインストール

Goがインストールされていない場合は、公式サイトからインストールしてください。
ターミナルで以下のコマンドを実行し、インストールが完了していることを確認します。

go version

出力例:

go version go1.21.4 darwin/amd64

2. プロジェクトディレクトリの作成

ターミナルを開き、以下のコマンドでプロジェクトディレクトリを作成します。

mkdir echo_jwt_auth
cd echo_jwt_auth

3. go.mod の初期化

Goモジュールを初期化し、必要な依存関係を追加します。

go mod init echo_jwt_auth
go get github.com/labstack/echo/v4
go get github.com/golang-jwt/jwt
go get github.com/joho/godotenv

4. .env ファイルの作成と秘密鍵の生成

JWTの署名に使用する秘密鍵を生成します。Mac環境では、opensslコマンドを使用して安全な秘密鍵を生成できます。

ターミナルで以下のコマンドを実行してください。

openssl rand -base64 32

このコマンドは、32バイトのランダムなデータをBase64エンコードした文字列を生成します。生成された文字列をコピーして、後ほど .env ファイルに貼り付けます。

例:

F2JS6V1YoAM9mxTcvaX0RjLHntQCyq7mTzftufvYmfU=

.env ファイルをプロジェクトのルートディレクトリに作成し、以下の内容を追加します。

JWT_SECRET=F2JS6V1YoAM9mxTcvaX0RjLHntQCyq7mTzftufvYmfU=

注意: .envファイルには機密情報を含めるため、バージョン管理システム(例:Git)には含めないように .gitignore に追加することをおすすめします。

主要なファイルの解説

プロジェクトのディレクトリ構造は以下の通りです:

echo_jwt_auth/
├── go.mod
├── server.go
├── go.sum
└── .env

go.mod

Goモジュールの設定ファイルで、プロジェクト名や依存関係を定義します。

module echo_jwt_auth

go 1.21.4

require (
    github.com/golang-jwt/jwt v3.2.2+incompatible
    github.com/labstack/echo/v4 v4.12.0
    github.com/joho/godotenv v1.5.1
)
  • module echo_jwt_auth: モジュール名を echo_jwt_auth に設定。
  • go 1.21.4: 使用するGoのバージョン。
  • require: 必要なパッケージを指定。

.env

環境変数を定義するファイルです。ここではJWTの秘密鍵を設定しています。

JWT_SECRET=F2JS6V1YoAM9mxTcvaX0RjLHntQCyq7mTzftufvYmfU=

注意: .envファイルには機密情報を含めるため、バージョン管理システム(例:Git)には含めないように .gitignore に追加することをおすすめします。

server.go

メインのサーバーコードです。Echoフレームワークを使用してJWT認証を実装します。コードを分割し、メイン関数を簡素化することで、可読性を高めています。

package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
    "time"

    "github.com/golang-jwt/jwt"
    "github.com/joho/godotenv"
    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
)

// Userはユーザー情報を表す構造体です
type User struct {
    Name     string `json:"name" xml:"name" form:"name" query:"name"`
    Email    string `json:"email" xml:"email" form:"email" query:"email"`
    Password string `json:"password" xml:"password" form:"password" query:"password"`
}

// JwtCustomClaimsはJWTのカスタムクレームを定義します
type JwtCustomClaims struct {
    Email string `json:"email"`
    Name  string `json:"name"`
    jwt.StandardClaims
}

func main() {
    // 環境変数の初期化
    if err := initEnv(); err != nil {
        log.Fatal(err)
    }

    // Echoインスタンスの作成
    e := echo.New()

    // ミドルウェアの設定
    configureMiddleware(e)

    // ルートの定義
    defineRoutes(e)

    // サーバーの起動
    if err := e.Start(":1323"); err != nil {
        log.Fatal("サーバーの起動に失敗しました:", err)
    }
}

// initEnvは.envファイルから環境変数を読み込みます
func initEnv() error {
    err := godotenv.Load()
    if err != nil {
        return fmt.Errorf(".envファイルの読み込みに失敗しました: %v", err)
    }

    if os.Getenv("JWT_SECRET") == "" {
        return fmt.Errorf("JWT_SECRETが.envファイルに設定されていません")
    }

    return nil
}

// configureMiddlewareはEchoに必要なミドルウェアを設定します
func configureMiddleware(e *echo.Echo) {
    e.Use(middleware.Logger())
    e.Use(middleware.Recover())
}

// defineRoutesはアプリケーションのルートとハンドラーを設定します
func defineRoutes(e *echo.Echo) {
    // 環境変数からJWTシークレットを取得
    jwtSecret := []byte(os.Getenv("JWT_SECRET"))

    // JWTミドルウェアの設定
    jwtMiddleware := middleware.JWTWithConfig(middleware.JWTConfig{
        SigningKey: jwtSecret,
        Claims:     &JwtCustomClaims{},
    })

    // パブリックルート: ログイン
    e.POST("/login", login)

    // 保護されたルート: Hello World
    e.GET("/", hello, jwtMiddleware)
}

// helloは保護されたハンドラーで、挨拶メッセージを返します
func hello(c echo.Context) error {
    return c.String(http.StatusOK, "Hello, World!")
}

// loginはユーザー認証を行い、JWTトークンを生成して返します
func login(c echo.Context) error {
    // リクエストのJSONをUser構造体にバインド
    user := new(User)
    if err := c.Bind(user); err != nil {
        log.Println("リクエストのバインドエラー:", err)
        return c.JSON(http.StatusBadRequest, echo.Map{"message": "無効な入力です"})
    }

    log.Println("ログイン試行:", user.Email)

    // 簡易的な認証チェック(実際のアプリケーションではデータベースと連携)
    if user.Email != "user@example.com" || user.Password != "password" {
        log.Println("認証エラー:", user.Email)
        return c.JSON(http.StatusUnauthorized, echo.Map{"message": "メールアドレスまたはパスワードが無効です"})
    }

    // JWTクレームの設定
    claims := &JwtCustomClaims{
        Email: user.Email,
        Name:  user.Name,
        StandardClaims: jwt.StandardClaims{
            ExpiresAt: time.Now().Add(72 * time.Hour).Unix(),
        },
    }

    // クレームを持つトークンを生成
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

    // トークンを署名
    t, err := token.SignedString(jwtSecret)
    if err != nil {
        log.Println("トークンの署名エラー:", err)
        return c.JSON(http.StatusInternalServerError, echo.Map{"message": "トークンを生成できませんでした"})
    }

    // トークンを返す
    return c.JSON(http.StatusOK, echo.Map{
        "token": t,
    })
}

サーバーの起動とテスト

サーバーの起動

以下のコマンドでサーバーを起動します。

go run server.go

サーバーが正常に起動すると、以下のようなログが表示されます:

2024/04/27 12:00:00 Listening on :1323

テスト手順

APIエンドポイントをテストするために、curlコマンドを使用します。以下の手順に従ってテストを行ってください。

1. ログインしてJWTトークンを取得

まず、ログインエンドポイントにユーザー情報を送信して、JWTトークンを取得します。

curl -X POST http://localhost:1323/login \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "password": "password", "name": "Sample User"}'

期待されるレスポンス

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJuYW1lIjoiU2FtcGxlIFVzZXIiLCJleHAiOjE3MzA4NTU1MTZ9.1AWyT7129JbdoZ6wx0YGLAXJxY1Y4DxeYxYZ0D75HMI"
}

このトークンを後続のリクエストで使用します。

2. 保護されたエンドポイントにアクセス

取得したJWTトークンを使用して、保護されたルートにアクセスします。

curl http://localhost:1323/ \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJuYW1lIjoiU2FtcGxlIFVzZXIiLCJleHAiOjE3MzA4NTU1MTZ9.1AWyT7129JbdoZ6wx0YGLAXJxY1Y4DxeYxYZ0D75HMI"

期待されるレスポンス

Hello, World!

3. 認証失敗時の挙動

不正なトークンやトークンを送信しない場合、アクセスは拒否されます。

: トークンを送信しない場合

curl http://localhost:1323/

期待されるレスポンス

{
  "message": "Missing or malformed JWT"
}

まとめ

本記事では、GolangとEchoフレームワークを使用して、JWT認証を実装する方法を解説しました。

学んだポイント

  • プロジェクトのセットアップ手順:

    • Goモジュールの初期化と依存関係の追加方法。
  • JWTの秘密鍵の生成方法(Mac環境):

    • opensslコマンドを使用した安全な秘密鍵の生成手順。
  • Echoフレームワークを用いた基本的なサーバー構築:

    • Echoインスタンスの初期化とミドルウェアの設定方法。
  • JWT認証の実装方法:

    • ユーザー認証のロジックとJWTトークンの生成・署名方法。
  • curlコマンドを使用した認証フローのテスト手順:

    • ログインエンドポイントへのリクエストとトークンを使用した保護されたエンドポイントへのアクセス方法。

参考リンク

これらのリソースを活用して、さらに深い理解と高度な機能の実装に挑戦してみてください!

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?