claims.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package login
  2. import (
  3. "errors"
  4. "net/http"
  5. "time"
  6. "github.com/golang-jwt/jwt/v4"
  7. "github.com/google/uuid"
  8. )
  9. var (
  10. errNoTokenString = errors.New("no token string")
  11. errTokenExpired = errors.New("token expired")
  12. errInvalidToken = errors.New("invalid token")
  13. )
  14. type UserClaims struct {
  15. Provider string
  16. Email string
  17. Name string
  18. UserID string
  19. AvatarURL string
  20. Location string
  21. IDToken string
  22. PassUpdatedAt string
  23. TOTPValidated bool
  24. jwt.RegisteredClaims
  25. }
  26. func mustSignClaims(claims jwt.Claims, secret string) string {
  27. token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  28. signed, err := token.SignedString([]byte(secret))
  29. if err != nil {
  30. panic(err)
  31. }
  32. return signed
  33. }
  34. func parseClaims(claims jwt.Claims, val string, secret string) (rc jwt.Claims, err error) {
  35. if val == "" {
  36. return nil, errNoTokenString
  37. }
  38. token, err := jwt.ParseWithClaims(val, claims, func(t *jwt.Token) (interface{}, error) {
  39. return []byte(secret), nil
  40. })
  41. if err != nil {
  42. if errors.Is(err, jwt.ErrTokenExpired) {
  43. return nil, errTokenExpired
  44. }
  45. return nil, errInvalidToken
  46. }
  47. if !token.Valid {
  48. return nil, errInvalidToken
  49. }
  50. return token.Claims, nil
  51. }
  52. func parseBaseClaims(val string, secret string) (rc *jwt.RegisteredClaims, err error) {
  53. c, err := parseClaims(&jwt.RegisteredClaims{}, val, secret)
  54. if err != nil {
  55. return nil, err
  56. }
  57. rc, ok := c.(*jwt.RegisteredClaims)
  58. if !ok {
  59. return nil, errInvalidToken
  60. }
  61. return rc, nil
  62. }
  63. func parseClaimsFromCookie(r *http.Request, cookieName string, claims jwt.Claims, secret string) (rc jwt.Claims, err error) {
  64. tc, err := r.Cookie(cookieName)
  65. if err != nil || tc.Value == "" {
  66. return nil, errNoTokenString
  67. }
  68. return parseClaims(claims, tc.Value, secret)
  69. }
  70. func parseUserClaimsFromCookie(r *http.Request, cookieName string, secret string) (rc *UserClaims, err error) {
  71. c, err := parseClaimsFromCookie(r, cookieName, &UserClaims{}, secret)
  72. if err != nil {
  73. return nil, err
  74. }
  75. rc, ok := c.(*UserClaims)
  76. if !ok {
  77. return nil, errInvalidToken
  78. }
  79. return rc, nil
  80. }
  81. func parseBaseClaimsFromCookie(r *http.Request, cookieName string, secret string) (rc *jwt.RegisteredClaims, err error) {
  82. c, err := parseClaimsFromCookie(r, cookieName, &jwt.RegisteredClaims{}, secret)
  83. if err != nil {
  84. return nil, err
  85. }
  86. rc, ok := c.(*jwt.RegisteredClaims)
  87. if !ok {
  88. return nil, errInvalidToken
  89. }
  90. return rc, nil
  91. }
  92. // maxAge seconds
  93. func genBaseClaims(sub string, maxAge int) jwt.RegisteredClaims {
  94. now := time.Now()
  95. return jwt.RegisteredClaims{
  96. ExpiresAt: jwt.NewNumericDate(now.Add(time.Duration(maxAge) * time.Second)),
  97. IssuedAt: jwt.NewNumericDate(now),
  98. NotBefore: jwt.NewNumericDate(now),
  99. Subject: sub,
  100. ID: uuid.New().String(),
  101. }
  102. }