github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/util/auth/token/jwt/jwt.go (about) 1 // Copyright 2020 Asim Aslam 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // Original source: github.com/micro/go-micro/v3/util/token/jwt/jwt.go 16 17 package jwt 18 19 import ( 20 "encoding/base64" 21 "strings" 22 "time" 23 24 "github.com/golang-jwt/jwt" 25 "github.com/tickoalcantara12/micro/v3/service/auth" 26 "github.com/tickoalcantara12/micro/v3/util/auth/token" 27 ) 28 29 // authClaims to be encoded in the JWT 30 type authClaims struct { 31 Type string `json:"type"` 32 Scopes []string `json:"scopes"` 33 Metadata map[string]string `json:"metadata"` 34 Name string `json:"name"` 35 36 jwt.StandardClaims 37 } 38 39 // JWT implementation of token provider 40 type JWT struct { 41 opts token.Options 42 } 43 44 // NewTokenProvider returns an initialized basic provider 45 func NewTokenProvider(opts ...token.Option) token.Provider { 46 return &JWT{ 47 opts: token.NewOptions(opts...), 48 } 49 } 50 51 // Generate a new JWT 52 func (j *JWT) Generate(acc *auth.Account, opts ...token.GenerateOption) (*token.Token, error) { 53 var priv []byte 54 if strings.HasPrefix(j.opts.PrivateKey, "-----BEGIN RSA PRIVATE KEY-----") { 55 priv = []byte(j.opts.PrivateKey) 56 } else { 57 var err error 58 priv, err = base64.StdEncoding.DecodeString(j.opts.PrivateKey) 59 if err != nil { 60 return nil, err 61 } 62 } 63 64 // parse the private key 65 key, err := jwt.ParseRSAPrivateKeyFromPEM(priv) 66 if err != nil { 67 return nil, token.ErrEncodingToken 68 } 69 70 // parse the options 71 options := token.NewGenerateOptions(opts...) 72 73 // backwards compatibility 74 name := acc.Name 75 if name == "" { 76 name = acc.ID 77 } 78 79 // generate the JWT 80 expiry := time.Now().Add(options.Expiry) 81 t := jwt.NewWithClaims(jwt.SigningMethodRS256, authClaims{ 82 Type: acc.Type, Scopes: acc.Scopes, Metadata: acc.Metadata, Name: name, 83 StandardClaims: jwt.StandardClaims{ 84 Subject: acc.ID, 85 Issuer: acc.Issuer, 86 ExpiresAt: expiry.Unix(), 87 }, 88 }) 89 tok, err := t.SignedString(key) 90 if err != nil { 91 return nil, err 92 } 93 94 // return the token 95 return &token.Token{ 96 Token: tok, 97 Expiry: expiry, 98 Created: time.Now(), 99 }, nil 100 } 101 102 // Inspect a JWT 103 func (j *JWT) Inspect(t string) (*auth.Account, error) { 104 // simple validation should be of form xxx.yyy.zzz i.e. contain two dots 105 if len(strings.Split(t, ".")) != 3 { 106 return nil, token.ErrInvalidToken 107 } 108 109 var pub []byte 110 if strings.HasPrefix(j.opts.PublicKey, "-----BEGIN CERTIFICATE-----") { 111 pub = []byte(j.opts.PublicKey) 112 } else { 113 var err error 114 pub, err = base64.StdEncoding.DecodeString(j.opts.PublicKey) 115 if err != nil { 116 return nil, err 117 } 118 } 119 120 // parse the public key 121 res, err := jwt.ParseWithClaims(t, &authClaims{}, func(token *jwt.Token) (interface{}, error) { 122 return jwt.ParseRSAPublicKeyFromPEM(pub) 123 }) 124 if err != nil { 125 return nil, token.ErrInvalidToken 126 } 127 128 // validate the token 129 if !res.Valid { 130 return nil, token.ErrInvalidToken 131 } 132 claims, ok := res.Claims.(*authClaims) 133 if !ok { 134 return nil, token.ErrInvalidToken 135 } 136 137 // backwards compatibility 138 name := claims.Name 139 if name == "" { 140 name = claims.Subject 141 } 142 143 // return the token 144 return &auth.Account{ 145 ID: claims.Subject, 146 Issuer: claims.Issuer, 147 Type: claims.Type, 148 Scopes: claims.Scopes, 149 Metadata: claims.Metadata, 150 Name: name, 151 }, nil 152 } 153 154 // String returns JWT 155 func (j *JWT) String() string { 156 return "jwt" 157 }