LCOV - code coverage report
Current view: top level - adapter/http/middleware - auth.go Coverage Total Hit
Test: coverage.lcov Lines: 74.1 % 58 43
Test Date: 2026-04-14 06:42:22 Functions: - 0 0

            Line data    Source code
       1              : package middleware
       2              : 
       3              : import (
       4              :         "net/http"
       5              :         "strings"
       6              : 
       7              :         "github.com/gin-gonic/gin"
       8              : 
       9              :         "resume/internal/adapter/gateway/firebase"
      10              :         "resume/internal/adapter/http/handlerutil"
      11              :         "resume/internal/shared/apperr"
      12              :         "resume/internal/shared/ctx/auth"
      13              : )
      14              : 
      15              : // Bearer extracts the token from an Authorization header in "Bearer <token>" format.
      16              : // It returns the token and true if successful, otherwise an empty string and false.
      17            3 : func Bearer(h string) (string, bool) {
      18            6 :         if h == "" {
      19            3 :                 return "", false
      20            3 :         }
      21            2 :         parts := strings.SplitN(h, " ", 2)
      22            2 :         if len(parts) != 2 || !strings.EqualFold(parts[0], "Bearer") {
      23            0 :                 return "", false
      24            0 :         }
      25            2 :         return parts[1], true
      26              : }
      27              : 
      28              : // InjectAuth は Authorization ヘッダーの Bearer トークンを検証し、
      29              : // 検証に成功した場合は認証クレーム(UID と email)をリクエストコンテキストへ注入します。
      30            2 : func InjectAuth(fb firebase.Auth) gin.HandlerFunc {
      31            4 :         return func(c *gin.Context) {
      32            2 :                 tok, ok := Bearer(c.GetHeader("Authorization"))
      33            3 :                 if !ok {
      34            1 :                         c.Next()
      35            1 :                         return
      36            1 :                 }
      37            1 :                 t, err := fb.VerifyIDToken(c.Request.Context(), tok)
      38            1 :                 if err != nil {
      39            0 :                         // 無効なら素通り or 401 を返すかは方針次第。ここでは素通りに。
      40            0 :                         c.Next()
      41            0 :                         return
      42            0 :                 }
      43            1 :                 email := ""
      44            2 :                 if v, ok := t.Claims["email"].(string); ok {
      45            1 :                         email = v
      46            1 :                 }
      47            1 :                 ctx := auth.With(c.Request.Context(), auth.Claims{
      48            1 :                         UID: t.UID, Email: email,
      49            1 :                 })
      50            1 :                 c.Request = c.Request.WithContext(ctx)
      51            1 :                 c.Next()
      52              :         }
      53              : }
      54              : 
      55              : // RequireAuth は Bearer トークンの存在と有効性を強制し、
      56              : // 失敗した場合は 401 を返して処理を中断します。成功時は認証クレームを注入します。
      57            3 : func RequireAuth(fb firebase.Auth) gin.HandlerFunc {
      58            5 :         return func(c *gin.Context) {
      59            2 :                 // ★ プリフライトは通す
      60            2 :                 if c.Request.Method == http.MethodOptions {
      61            0 :                         c.Next()
      62            0 :                         return
      63            0 :                 }
      64              : 
      65            2 :                 tok, ok := Bearer(c.GetHeader("Authorization"))
      66            4 :                 if !ok {
      67            2 :                         handlerutil.WriteError(c, apperr.New(apperr.CodeUnauthorized, "unauthorized", nil))
      68            2 :                         return
      69            2 :                 }
      70              : 
      71            1 :                 t, err := fb.VerifyIDToken(c.Request.Context(), tok)
      72            1 :                 if err != nil {
      73            0 :                         handlerutil.WriteError(
      74            0 :                                 c,
      75            0 :                                 apperr.Wrap(apperr.CodeUnauthorized, "invalid token", err, nil),
      76            0 :                         )
      77            0 :                         return
      78            0 :                 }
      79              : 
      80            1 :                 email := ""
      81            2 :                 if v, ok := t.Claims["email"].(string); ok {
      82            1 :                         email = v
      83            1 :                 }
      84            1 :                 ctx := auth.With(c.Request.Context(), auth.Claims{UID: t.UID, Email: email})
      85            1 :                 c.Request = c.Request.WithContext(ctx)
      86            1 :                 c.Next()
      87              :         }
      88              : }
        

Generated by: LCOV version 2.3.1-1