satellite/console: retrieve a web UI session using a API key
retrieve a web UI session using a API key and add new test Issue https://github.com/storj/storj/issues/5688 Change-Id: I0ad9c783f0573b87b212b8fb065cdbf7074b782c
This commit is contained in:
parent
81b2b067e6
commit
7e69b22dd4
@ -125,6 +125,49 @@ func (a *Auth) Token(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// TokenByAPIKey authenticates user by API key and returns auth token.
|
||||
func (a *Auth) TokenByAPIKey(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
var err error
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
authToken := r.Header.Get("Authorization")
|
||||
split := strings.Split(authToken, "Bearer ")
|
||||
if len(split) != 2 {
|
||||
a.log.Info("authorization key format is incorrect. Should be 'Bearer <key>'")
|
||||
a.serveJSONError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
apiKey := split[1]
|
||||
|
||||
userAgent := r.UserAgent()
|
||||
ip, err := web.GetRequestIP(r)
|
||||
if err != nil {
|
||||
a.serveJSONError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
tokenInfo, err := a.service.TokenByAPIKey(ctx, userAgent, ip, apiKey)
|
||||
if err != nil {
|
||||
a.log.Info("Error authenticating token request", zap.Error(ErrAuthAPI.Wrap(err)))
|
||||
a.serveJSONError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
a.cookieAuth.SetTokenCookie(w, *tokenInfo)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
err = json.NewEncoder(w).Encode(struct {
|
||||
console.TokenInfo
|
||||
Token string `json:"token"`
|
||||
}{*tokenInfo, tokenInfo.Token.String()})
|
||||
if err != nil {
|
||||
a.log.Error("token handler could not encode token response", zap.Error(ErrAuthAPI.Wrap(err)))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// getSessionID gets the session ID from the request.
|
||||
func (a *Auth) getSessionID(r *http.Request) (id uuid.UUID, err error) {
|
||||
|
||||
|
@ -329,6 +329,42 @@ returned response:
|
||||
}
|
||||
}
|
||||
|
||||
func TestTokenByAPIKeyEndpoint(t *testing.T) {
|
||||
testplanet.Run(t, testplanet.Config{
|
||||
SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 0,
|
||||
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||
satellite := planet.Satellites[0]
|
||||
restKeys := satellite.API.REST.Keys
|
||||
|
||||
user, err := satellite.AddUser(ctx, console.CreateUser{
|
||||
FullName: "Test User",
|
||||
Email: "test@mail.test",
|
||||
}, 1)
|
||||
require.NoError(t, err)
|
||||
|
||||
expires := 5 * time.Hour
|
||||
apiKey, _, err := restKeys.Create(ctx, user.ID, expires)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, apiKey)
|
||||
|
||||
url := planet.Satellites[0].ConsoleURL() + "/api/v0/auth/token-by-api-key"
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, nil)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Authorization", "Bearer "+apiKey)
|
||||
|
||||
response, err := http.DefaultClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, response)
|
||||
require.NoError(t, response.Body.Close())
|
||||
|
||||
cookies := response.Cookies()
|
||||
require.NoError(t, err)
|
||||
require.Len(t, cookies, 1)
|
||||
require.Equal(t, "_tokenKey", cookies[0].Name)
|
||||
require.NotEmpty(t, cookies[0].Value)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMFAEndpoints(t *testing.T) {
|
||||
testplanet.Run(t, testplanet.Config{
|
||||
SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 0,
|
||||
|
@ -285,6 +285,7 @@ func NewServer(logger *zap.Logger, config Config, service *console.Service, oidc
|
||||
authRouter.Handle("/mfa/generate-recovery-codes", server.withAuth(http.HandlerFunc(authController.GenerateMFARecoveryCodes))).Methods(http.MethodPost)
|
||||
authRouter.Handle("/logout", server.withAuth(http.HandlerFunc(authController.Logout))).Methods(http.MethodPost)
|
||||
authRouter.Handle("/token", server.ipRateLimiter.Limit(http.HandlerFunc(authController.Token))).Methods(http.MethodPost)
|
||||
authRouter.Handle("/token-by-api-key", server.ipRateLimiter.Limit(http.HandlerFunc(authController.TokenByAPIKey))).Methods(http.MethodPost)
|
||||
authRouter.Handle("/register", server.ipRateLimiter.Limit(http.HandlerFunc(authController.Register))).Methods(http.MethodPost, http.MethodOptions)
|
||||
authRouter.Handle("/forgot-password", server.ipRateLimiter.Limit(http.HandlerFunc(authController.ForgotPassword))).Methods(http.MethodPost)
|
||||
authRouter.Handle("/resend-email/{email}", server.ipRateLimiter.Limit(http.HandlerFunc(authController.ResendEmail))).Methods(http.MethodPost)
|
||||
|
@ -57,6 +57,9 @@ const (
|
||||
emailNotFoundErrMsg = "There are no users with the specified email"
|
||||
passwordRecoveryTokenIsExpiredErrMsg = "Your password recovery link has expired, please request another one"
|
||||
credentialsErrMsg = "Your login credentials are incorrect, please try again"
|
||||
generateSessionTokenErrMsg = "Failed to generate session token"
|
||||
failedToRetrieveUserErrMsg = "Failed to retrieve user from database"
|
||||
apiKeyCredentialsErrMsg = "Your API Key is incorrect"
|
||||
changePasswordErrMsg = "Your old password is incorrect, please try again"
|
||||
passwordTooShortErrMsg = "Your password needs to be at least %d characters long"
|
||||
passwordTooLongErrMsg = "Your password must be no longer than %d characters"
|
||||
@ -1206,6 +1209,28 @@ func (s *Service) Token(ctx context.Context, request AuthUser) (response *TokenI
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// TokenByAPIKey authenticates User by API Key and returns session token.
|
||||
func (s *Service) TokenByAPIKey(ctx context.Context, userAgent string, ip string, apiKey string) (response *TokenInfo, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
userID, _, err := s.restKeys.GetUserAndExpirationFromKey(ctx, apiKey)
|
||||
if err != nil {
|
||||
return nil, ErrUnauthorized.New(apiKeyCredentialsErrMsg)
|
||||
}
|
||||
|
||||
user, err := s.store.Users().Get(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, Error.New(failedToRetrieveUserErrMsg)
|
||||
}
|
||||
|
||||
response, err = s.GenerateSessionToken(ctx, user.ID, user.Email, ip, userAgent)
|
||||
if err != nil {
|
||||
return nil, Error.New(generateSessionTokenErrMsg)
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// UpdateUsersFailedLoginState updates User's failed login state.
|
||||
func (s *Service) UpdateUsersFailedLoginState(ctx context.Context, user *User) (err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
Loading…
Reference in New Issue
Block a user