storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/jwt.go (about) 1 /* 2 * MinIO Cloud Storage, (C) 2016-2020 MinIO, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package cmd 18 19 import ( 20 "context" 21 "errors" 22 "net/http" 23 "time" 24 25 jwtgo "github.com/dgrijalva/jwt-go" 26 jwtreq "github.com/dgrijalva/jwt-go/request" 27 28 xjwt "storj.io/minio/cmd/jwt" 29 "storj.io/minio/cmd/logger" 30 "storj.io/minio/pkg/auth" 31 ) 32 33 const ( 34 jwtAlgorithm = "Bearer" 35 36 // Default JWT token for web handlers is one day. 37 defaultJWTExpiry = 24 * time.Hour 38 39 // Inter-node JWT token expiry is 15 minutes. 40 defaultInterNodeJWTExpiry = 15 * time.Minute 41 42 // URL JWT token expiry is one minute (might be exposed). 43 defaultURLJWTExpiry = time.Minute 44 ) 45 46 var ( 47 errInvalidAccessKeyID = errors.New("The access key ID you provided does not exist in our records") 48 errChangeCredNotAllowed = errors.New("Changing access key and secret key not allowed") 49 errAuthentication = errors.New("Authentication failed, check your access credentials") 50 errNoAuthToken = errors.New("JWT token missing") 51 errIncorrectCreds = errors.New("Current access key or secret key is incorrect") 52 errPresignedNotAllowed = errors.New("Unable to generate shareable URL due to lack of read permissions") 53 ) 54 55 func authenticateJWTUsers(accessKey, secretKey string, expiry time.Duration) (string, error) { 56 passedCredential, err := auth.CreateCredentials(accessKey, secretKey) 57 if err != nil { 58 return "", err 59 } 60 expiresAt := UTCNow().Add(expiry) 61 return authenticateJWTUsersWithCredentials(passedCredential, expiresAt) 62 } 63 64 func authenticateJWTUsersWithCredentials(credentials auth.Credentials, expiresAt time.Time) (string, error) { 65 serverCred := globalActiveCred 66 if serverCred.AccessKey != credentials.AccessKey { 67 var ok bool 68 serverCred, ok = GlobalIAMSys.GetUser(context.Background(), credentials.AccessKey) 69 if !ok { 70 return "", errInvalidAccessKeyID 71 } 72 } 73 74 if !serverCred.Equal(credentials) { 75 return "", errAuthentication 76 } 77 78 claims := xjwt.NewMapClaims() 79 claims.SetExpiry(expiresAt) 80 claims.SetAccessKey(credentials.AccessKey) 81 82 jwt := jwtgo.NewWithClaims(jwtgo.SigningMethodHS512, claims) 83 return jwt.SignedString([]byte(serverCred.SecretKey)) 84 } 85 86 func authenticateNode(accessKey, secretKey, audience string) (string, error) { 87 claims := xjwt.NewStandardClaims() 88 claims.SetExpiry(UTCNow().Add(defaultInterNodeJWTExpiry)) 89 claims.SetAccessKey(accessKey) 90 claims.SetAudience(audience) 91 92 jwt := jwtgo.NewWithClaims(jwtgo.SigningMethodHS512, claims) 93 return jwt.SignedString([]byte(secretKey)) 94 } 95 96 func authenticateWeb(accessKey, secretKey string) (string, error) { 97 return authenticateJWTUsers(accessKey, secretKey, defaultJWTExpiry) 98 } 99 100 func authenticateURL(accessKey, secretKey string) (string, error) { 101 return authenticateJWTUsers(accessKey, secretKey, defaultURLJWTExpiry) 102 } 103 104 // Callback function used for parsing 105 func webTokenCallback(claims *xjwt.MapClaims) ([]byte, error) { 106 if claims.AccessKey == globalActiveCred.AccessKey { 107 return []byte(globalActiveCred.SecretKey), nil 108 } 109 ok, _, err := GlobalIAMSys.IsTempUser(claims.AccessKey) 110 if err != nil { 111 if err == errNoSuchUser { 112 return nil, errInvalidAccessKeyID 113 } 114 return nil, err 115 } 116 if ok { 117 return []byte(globalActiveCred.SecretKey), nil 118 } 119 cred, ok := GlobalIAMSys.GetUser(context.Background(), claims.AccessKey) 120 if !ok { 121 return nil, errInvalidAccessKeyID 122 } 123 return []byte(cred.SecretKey), nil 124 125 } 126 127 func isAuthTokenValid(token string) bool { 128 _, _, err := webTokenAuthenticate(token) 129 return err == nil 130 } 131 132 func webTokenAuthenticate(token string) (*xjwt.MapClaims, bool, error) { 133 if token == "" { 134 return nil, false, errNoAuthToken 135 } 136 claims := xjwt.NewMapClaims() 137 if err := xjwt.ParseWithClaims(token, claims, webTokenCallback); err != nil { 138 return claims, false, errAuthentication 139 } 140 owner := claims.AccessKey == globalActiveCred.AccessKey 141 return claims, owner, nil 142 } 143 144 // Check if the request is authenticated. 145 // Returns nil if the request is authenticated. errNoAuthToken if token missing. 146 // Returns errAuthentication for all other errors. 147 func webRequestAuthenticate(req *http.Request) (*xjwt.MapClaims, bool, error) { 148 token, err := jwtreq.AuthorizationHeaderExtractor.ExtractToken(req) 149 if err != nil { 150 if err == jwtreq.ErrNoTokenInRequest { 151 return nil, false, errNoAuthToken 152 } 153 return nil, false, err 154 } 155 claims := xjwt.NewMapClaims() 156 if err := xjwt.ParseWithClaims(token, claims, webTokenCallback); err != nil { 157 return claims, false, errAuthentication 158 } 159 owner := claims.AccessKey == globalActiveCred.AccessKey 160 return claims, owner, nil 161 } 162 163 func newAuthToken(audience string) string { 164 cred := globalActiveCred 165 token, err := authenticateNode(cred.AccessKey, cred.SecretKey, audience) 166 logger.CriticalIf(GlobalContext, err) 167 return token 168 }