Fixed broken oauth2 login for operator (#1217)
This PR includes many fixes and refactors for oauth2 authentication and login endpoints, ie: - Invalid login returns `403` instead of `500` error - Removed the session token from console/operator `user credentials login`, `oauth flow login` and `change-password` api responses - Removed session token from localStorage - Added styles for oauth_callback page and display more descriptive errors for debugging - Success logins returns `204` instead of `200` - Removed unused swagger apis and code from both, operator and console projects - Operator `Oauth2` login flow was not validating anything, now it does Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
This commit is contained in:
@@ -123,16 +123,17 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
if response != nil {
|
||||
bodyBytes, _ := ioutil.ReadAll(response.Body)
|
||||
|
||||
loginResponse := models.LoginResponse{}
|
||||
err = json.Unmarshal(bodyBytes, &loginResponse)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
for _, cookie := range response.Cookies() {
|
||||
if cookie.Name == "token" {
|
||||
token = cookie.Value
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
token = loginResponse.SessionID
|
||||
|
||||
if token == "" {
|
||||
log.Println("authentication token not found in cookies response")
|
||||
return
|
||||
}
|
||||
|
||||
code := m.Run()
|
||||
|
||||
@@ -272,38 +272,6 @@ func init() {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"security": [],
|
||||
"tags": [
|
||||
"UserAPI"
|
||||
],
|
||||
"summary": "Login to Console",
|
||||
"operationId": "Login",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/login/oauth2/auth": {
|
||||
@@ -325,11 +293,8 @@ func init() {
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
"204": {
|
||||
"description": "A successful login."
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
@@ -359,11 +324,8 @@ func init() {
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
"204": {
|
||||
"description": "A successful login."
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
@@ -2215,14 +2177,6 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"loginResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sessionId": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"maxAllocatableMemResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -3456,38 +3410,6 @@ func init() {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"security": [],
|
||||
"tags": [
|
||||
"UserAPI"
|
||||
],
|
||||
"summary": "Login to Console",
|
||||
"operationId": "Login",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/login/oauth2/auth": {
|
||||
@@ -3509,11 +3431,8 @@ func init() {
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
"204": {
|
||||
"description": "A successful login."
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
@@ -3543,11 +3462,8 @@ func init() {
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
"204": {
|
||||
"description": "A successful login."
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
@@ -6112,14 +6028,6 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"loginResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sessionId": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"maxAllocatableMemResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -123,9 +123,6 @@ func NewOperatorAPI(spec *loads.Document) *OperatorAPI {
|
||||
OperatorAPIListTenantsHandler: operator_api.ListTenantsHandlerFunc(func(params operator_api.ListTenantsParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation operator_api.ListTenants has not yet been implemented")
|
||||
}),
|
||||
UserAPILoginHandler: user_api.LoginHandlerFunc(func(params user_api.LoginParams) middleware.Responder {
|
||||
return middleware.NotImplemented("operation user_api.Login has not yet been implemented")
|
||||
}),
|
||||
UserAPILoginDetailHandler: user_api.LoginDetailHandlerFunc(func(params user_api.LoginDetailParams) middleware.Responder {
|
||||
return middleware.NotImplemented("operation user_api.LoginDetail has not yet been implemented")
|
||||
}),
|
||||
@@ -269,8 +266,6 @@ type OperatorAPI struct {
|
||||
OperatorAPIListPVCsForTenantHandler operator_api.ListPVCsForTenantHandler
|
||||
// OperatorAPIListTenantsHandler sets the operation handler for the list tenants operation
|
||||
OperatorAPIListTenantsHandler operator_api.ListTenantsHandler
|
||||
// UserAPILoginHandler sets the operation handler for the login operation
|
||||
UserAPILoginHandler user_api.LoginHandler
|
||||
// UserAPILoginDetailHandler sets the operation handler for the login detail operation
|
||||
UserAPILoginDetailHandler user_api.LoginDetailHandler
|
||||
// UserAPILoginOauth2AuthHandler sets the operation handler for the login oauth2 auth operation
|
||||
@@ -448,9 +443,6 @@ func (o *OperatorAPI) Validate() error {
|
||||
if o.OperatorAPIListTenantsHandler == nil {
|
||||
unregistered = append(unregistered, "operator_api.ListTenantsHandler")
|
||||
}
|
||||
if o.UserAPILoginHandler == nil {
|
||||
unregistered = append(unregistered, "user_api.LoginHandler")
|
||||
}
|
||||
if o.UserAPILoginDetailHandler == nil {
|
||||
unregistered = append(unregistered, "user_api.LoginDetailHandler")
|
||||
}
|
||||
@@ -683,10 +675,6 @@ func (o *OperatorAPI) initHandlerCache() {
|
||||
o.handlers["GET"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["GET"]["/namespaces/{namespace}/tenants"] = operator_api.NewListTenants(o.context, o.OperatorAPIListTenantsHandler)
|
||||
if o.handlers["POST"] == nil {
|
||||
o.handlers["POST"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["POST"]["/login"] = user_api.NewLogin(o.context, o.UserAPILoginHandler)
|
||||
if o.handlers["GET"] == nil {
|
||||
o.handlers["GET"] = make(map[string]http.Handler)
|
||||
}
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package user_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
)
|
||||
|
||||
// LoginHandlerFunc turns a function with the right signature into a login handler
|
||||
type LoginHandlerFunc func(LoginParams) middleware.Responder
|
||||
|
||||
// Handle executing the request and returning a response
|
||||
func (fn LoginHandlerFunc) Handle(params LoginParams) middleware.Responder {
|
||||
return fn(params)
|
||||
}
|
||||
|
||||
// LoginHandler interface for that can handle valid login params
|
||||
type LoginHandler interface {
|
||||
Handle(LoginParams) middleware.Responder
|
||||
}
|
||||
|
||||
// NewLogin creates a new http.Handler for the login operation
|
||||
func NewLogin(ctx *middleware.Context, handler LoginHandler) *Login {
|
||||
return &Login{Context: ctx, Handler: handler}
|
||||
}
|
||||
|
||||
/* Login swagger:route POST /login UserAPI login
|
||||
|
||||
Login to Console
|
||||
|
||||
*/
|
||||
type Login struct {
|
||||
Context *middleware.Context
|
||||
Handler LoginHandler
|
||||
}
|
||||
|
||||
func (o *Login) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||
if rCtx != nil {
|
||||
*r = *rCtx
|
||||
}
|
||||
var Params = NewLoginParams()
|
||||
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
|
||||
o.Context.Respond(rw, r, route.Produces, route, err)
|
||||
return
|
||||
}
|
||||
|
||||
res := o.Handler.Handle(Params) // actually handle the request
|
||||
o.Context.Respond(rw, r, route.Produces, route, res)
|
||||
|
||||
}
|
||||
@@ -30,48 +30,28 @@ import (
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// LoginOauth2AuthCreatedCode is the HTTP code returned for type LoginOauth2AuthCreated
|
||||
const LoginOauth2AuthCreatedCode int = 201
|
||||
// LoginOauth2AuthNoContentCode is the HTTP code returned for type LoginOauth2AuthNoContent
|
||||
const LoginOauth2AuthNoContentCode int = 204
|
||||
|
||||
/*LoginOauth2AuthCreated A successful login.
|
||||
/*LoginOauth2AuthNoContent A successful login.
|
||||
|
||||
swagger:response loginOauth2AuthCreated
|
||||
swagger:response loginOauth2AuthNoContent
|
||||
*/
|
||||
type LoginOauth2AuthCreated struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.LoginResponse `json:"body,omitempty"`
|
||||
type LoginOauth2AuthNoContent struct {
|
||||
}
|
||||
|
||||
// NewLoginOauth2AuthCreated creates LoginOauth2AuthCreated with default headers values
|
||||
func NewLoginOauth2AuthCreated() *LoginOauth2AuthCreated {
|
||||
// NewLoginOauth2AuthNoContent creates LoginOauth2AuthNoContent with default headers values
|
||||
func NewLoginOauth2AuthNoContent() *LoginOauth2AuthNoContent {
|
||||
|
||||
return &LoginOauth2AuthCreated{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the login oauth2 auth created response
|
||||
func (o *LoginOauth2AuthCreated) WithPayload(payload *models.LoginResponse) *LoginOauth2AuthCreated {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the login oauth2 auth created response
|
||||
func (o *LoginOauth2AuthCreated) SetPayload(payload *models.LoginResponse) {
|
||||
o.Payload = payload
|
||||
return &LoginOauth2AuthNoContent{}
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *LoginOauth2AuthCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
func (o *LoginOauth2AuthNoContent) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(201)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
|
||||
|
||||
rw.WriteHeader(204)
|
||||
}
|
||||
|
||||
/*LoginOauth2AuthDefault Generic error response.
|
||||
|
||||
@@ -30,48 +30,28 @@ import (
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// LoginOperatorCreatedCode is the HTTP code returned for type LoginOperatorCreated
|
||||
const LoginOperatorCreatedCode int = 201
|
||||
// LoginOperatorNoContentCode is the HTTP code returned for type LoginOperatorNoContent
|
||||
const LoginOperatorNoContentCode int = 204
|
||||
|
||||
/*LoginOperatorCreated A successful login.
|
||||
/*LoginOperatorNoContent A successful login.
|
||||
|
||||
swagger:response loginOperatorCreated
|
||||
swagger:response loginOperatorNoContent
|
||||
*/
|
||||
type LoginOperatorCreated struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.LoginResponse `json:"body,omitempty"`
|
||||
type LoginOperatorNoContent struct {
|
||||
}
|
||||
|
||||
// NewLoginOperatorCreated creates LoginOperatorCreated with default headers values
|
||||
func NewLoginOperatorCreated() *LoginOperatorCreated {
|
||||
// NewLoginOperatorNoContent creates LoginOperatorNoContent with default headers values
|
||||
func NewLoginOperatorNoContent() *LoginOperatorNoContent {
|
||||
|
||||
return &LoginOperatorCreated{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the login operator created response
|
||||
func (o *LoginOperatorCreated) WithPayload(payload *models.LoginResponse) *LoginOperatorCreated {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the login operator created response
|
||||
func (o *LoginOperatorCreated) SetPayload(payload *models.LoginResponse) {
|
||||
o.Payload = payload
|
||||
return &LoginOperatorNoContent{}
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *LoginOperatorCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
func (o *LoginOperatorNoContent) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(201)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
|
||||
|
||||
rw.WriteHeader(204)
|
||||
}
|
||||
|
||||
/*LoginOperatorDefault Generic error response.
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package user_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/validate"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// NewLoginParams creates a new LoginParams object
|
||||
//
|
||||
// There are no default values defined in the spec.
|
||||
func NewLoginParams() LoginParams {
|
||||
|
||||
return LoginParams{}
|
||||
}
|
||||
|
||||
// LoginParams contains all the bound params for the login operation
|
||||
// typically these are obtained from a http.Request
|
||||
//
|
||||
// swagger:parameters Login
|
||||
type LoginParams struct {
|
||||
|
||||
// HTTP Request Object
|
||||
HTTPRequest *http.Request `json:"-"`
|
||||
|
||||
/*
|
||||
Required: true
|
||||
In: body
|
||||
*/
|
||||
Body *models.LoginRequest
|
||||
}
|
||||
|
||||
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
|
||||
// for simple values it will use straight method calls.
|
||||
//
|
||||
// To ensure default values, the struct must have been initialized with NewLoginParams() beforehand.
|
||||
func (o *LoginParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||
var res []error
|
||||
|
||||
o.HTTPRequest = r
|
||||
|
||||
if runtime.HasBody(r) {
|
||||
defer r.Body.Close()
|
||||
var body models.LoginRequest
|
||||
if err := route.Consumer.Consume(r.Body, &body); err != nil {
|
||||
if err == io.EOF {
|
||||
res = append(res, errors.Required("body", "body", ""))
|
||||
} else {
|
||||
res = append(res, errors.NewParseError("body", "body", "", err))
|
||||
}
|
||||
} else {
|
||||
// validate body object
|
||||
if err := body.Validate(route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
ctx := validate.WithOperationRequest(context.Background())
|
||||
if err := body.ContextValidate(ctx, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) == 0 {
|
||||
o.Body = &body
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = append(res, errors.Required("body", "body", ""))
|
||||
}
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package user_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// LoginCreatedCode is the HTTP code returned for type LoginCreated
|
||||
const LoginCreatedCode int = 201
|
||||
|
||||
/*LoginCreated A successful login.
|
||||
|
||||
swagger:response loginCreated
|
||||
*/
|
||||
type LoginCreated struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.LoginResponse `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewLoginCreated creates LoginCreated with default headers values
|
||||
func NewLoginCreated() *LoginCreated {
|
||||
|
||||
return &LoginCreated{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the login created response
|
||||
func (o *LoginCreated) WithPayload(payload *models.LoginResponse) *LoginCreated {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the login created response
|
||||
func (o *LoginCreated) SetPayload(payload *models.LoginResponse) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *LoginCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(201)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*LoginDefault Generic error response.
|
||||
|
||||
swagger:response loginDefault
|
||||
*/
|
||||
type LoginDefault struct {
|
||||
_statusCode int
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.Error `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewLoginDefault creates LoginDefault with default headers values
|
||||
func NewLoginDefault(code int) *LoginDefault {
|
||||
if code <= 0 {
|
||||
code = 500
|
||||
}
|
||||
|
||||
return &LoginDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
// WithStatusCode adds the status to the login default response
|
||||
func (o *LoginDefault) WithStatusCode(code int) *LoginDefault {
|
||||
o._statusCode = code
|
||||
return o
|
||||
}
|
||||
|
||||
// SetStatusCode sets the status to the login default response
|
||||
func (o *LoginDefault) SetStatusCode(code int) {
|
||||
o._statusCode = code
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the login default response
|
||||
func (o *LoginDefault) WithPayload(payload *models.Error) *LoginDefault {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the login default response
|
||||
func (o *LoginDefault) SetPayload(payload *models.Error) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *LoginDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(o._statusCode)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package user_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the generate command
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
golangswaggerpaths "path"
|
||||
)
|
||||
|
||||
// LoginURL generates an URL for the login operation
|
||||
type LoginURL struct {
|
||||
_basePath string
|
||||
}
|
||||
|
||||
// WithBasePath sets the base path for this url builder, only required when it's different from the
|
||||
// base path specified in the swagger spec.
|
||||
// When the value of the base path is an empty string
|
||||
func (o *LoginURL) WithBasePath(bp string) *LoginURL {
|
||||
o.SetBasePath(bp)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetBasePath sets the base path for this url builder, only required when it's different from the
|
||||
// base path specified in the swagger spec.
|
||||
// When the value of the base path is an empty string
|
||||
func (o *LoginURL) SetBasePath(bp string) {
|
||||
o._basePath = bp
|
||||
}
|
||||
|
||||
// Build a url path and query string
|
||||
func (o *LoginURL) Build() (*url.URL, error) {
|
||||
var _result url.URL
|
||||
|
||||
var _path = "/login"
|
||||
|
||||
_basePath := o._basePath
|
||||
if _basePath == "" {
|
||||
_basePath = "/api/v1"
|
||||
}
|
||||
_result.Path = golangswaggerpaths.Join(_basePath, _path)
|
||||
|
||||
return &_result, nil
|
||||
}
|
||||
|
||||
// Must is a helper function to panic when the url builder returns an error
|
||||
func (o *LoginURL) Must(u *url.URL, err error) *url.URL {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if u == nil {
|
||||
panic("url can't be nil")
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
// String returns the string representation of the path with query string
|
||||
func (o *LoginURL) String() string {
|
||||
return o.Must(o.Build()).String()
|
||||
}
|
||||
|
||||
// BuildFull builds a full url with scheme, host, path and query string
|
||||
func (o *LoginURL) BuildFull(scheme, host string) (*url.URL, error) {
|
||||
if scheme == "" {
|
||||
return nil, errors.New("scheme is required for a full url on LoginURL")
|
||||
}
|
||||
if host == "" {
|
||||
return nil, errors.New("host is required for a full url on LoginURL")
|
||||
}
|
||||
|
||||
base, err := o.Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
base.Scheme = scheme
|
||||
base.Host = host
|
||||
return base, nil
|
||||
}
|
||||
|
||||
// StringFull returns the string representation of a complete url
|
||||
func (o *LoginURL) StringFull(scheme, host string) string {
|
||||
return o.Must(o.BuildFull(scheme, host)).String()
|
||||
}
|
||||
@@ -17,7 +17,11 @@
|
||||
package operatorapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
xoauth2 "golang.org/x/oauth2"
|
||||
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
|
||||
@@ -33,7 +37,7 @@ import (
|
||||
)
|
||||
|
||||
func registerLoginHandlers(api *operations.OperatorAPI) {
|
||||
// get login strategy
|
||||
// GET login strategy
|
||||
api.UserAPILoginDetailHandler = user_api.LoginDetailHandlerFunc(func(params user_api.LoginDetailParams) middleware.Responder {
|
||||
loginDetails, err := getLoginDetailsResponse()
|
||||
if err != nil {
|
||||
@@ -41,31 +45,7 @@ func registerLoginHandlers(api *operations.OperatorAPI) {
|
||||
}
|
||||
return user_api.NewLoginDetailOK().WithPayload(loginDetails)
|
||||
})
|
||||
// post login
|
||||
api.UserAPILoginHandler = user_api.LoginHandlerFunc(func(params user_api.LoginParams) middleware.Responder {
|
||||
loginResponse, err := getLoginResponse(params.Body)
|
||||
if err != nil {
|
||||
return user_api.NewLoginDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
// Custom response writer to set the session cookies
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
|
||||
cookie := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
|
||||
http.SetCookie(w, &cookie)
|
||||
user_api.NewLoginCreated().WithPayload(loginResponse).WriteResponse(w, p)
|
||||
})
|
||||
})
|
||||
api.UserAPILoginOauth2AuthHandler = user_api.LoginOauth2AuthHandlerFunc(func(params user_api.LoginOauth2AuthParams) middleware.Responder {
|
||||
loginResponse, err := getLoginOauth2AuthResponse()
|
||||
if err != nil {
|
||||
return user_api.NewLoginOauth2AuthDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
// Custom response writer to set the session cookies
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
|
||||
cookie := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
|
||||
http.SetCookie(w, &cookie)
|
||||
user_api.NewLoginOauth2AuthCreated().WithPayload(loginResponse).WriteResponse(w, p)
|
||||
})
|
||||
})
|
||||
// POST login using k8s service account token
|
||||
api.UserAPILoginOperatorHandler = user_api.LoginOperatorHandlerFunc(func(params user_api.LoginOperatorParams) middleware.Responder {
|
||||
loginResponse, err := getLoginOperatorResponse(params.Body)
|
||||
if err != nil {
|
||||
@@ -75,7 +55,20 @@ func registerLoginHandlers(api *operations.OperatorAPI) {
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
|
||||
cookie := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
|
||||
http.SetCookie(w, &cookie)
|
||||
user_api.NewLoginOperatorCreated().WithPayload(loginResponse).WriteResponse(w, p)
|
||||
user_api.NewLoginOperatorNoContent().WriteResponse(w, p)
|
||||
})
|
||||
})
|
||||
// POST login using external IDP
|
||||
api.UserAPILoginOauth2AuthHandler = user_api.LoginOauth2AuthHandlerFunc(func(params user_api.LoginOauth2AuthParams) middleware.Responder {
|
||||
loginResponse, err := getLoginOauth2AuthResponse(params.Body)
|
||||
if err != nil {
|
||||
return user_api.NewLoginOauth2AuthDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
// Custom response writer to set the session cookies
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
|
||||
cookie := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
|
||||
http.SetCookie(w, &cookie)
|
||||
user_api.NewLoginOauth2AuthNoContent().WriteResponse(w, p)
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -97,36 +90,6 @@ func login(credentials restapi.ConsoleCredentialsI) (*string, error) {
|
||||
return &token, nil
|
||||
}
|
||||
|
||||
// getConsoleCredentials will return consoleCredentials interface including the associated policy of the current account
|
||||
func getConsoleCredentials(accessKey, secretKey string) (*restapi.ConsoleCredentials, error) {
|
||||
creds, err := newConsoleCredentials(secretKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &restapi.ConsoleCredentials{
|
||||
ConsoleCredentials: creds,
|
||||
AccountAccessKey: accessKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// getLoginResponse performs login() and serializes it to the handler's output
|
||||
func getLoginResponse(lr *models.LoginRequest) (*models.LoginResponse, *models.Error) {
|
||||
// prepare console credentials
|
||||
consolCreds, err := getConsoleCredentials(*lr.AccessKey, *lr.SecretKey)
|
||||
if err != nil {
|
||||
return nil, prepareError(errInvalidCredentials, nil, err)
|
||||
}
|
||||
sessionID, err := login(consolCreds)
|
||||
if err != nil {
|
||||
return nil, prepareError(errInvalidCredentials, nil, err)
|
||||
}
|
||||
// serialize output
|
||||
loginResponse := &models.LoginResponse{
|
||||
SessionID: *sessionID,
|
||||
}
|
||||
return loginResponse, nil
|
||||
}
|
||||
|
||||
// getLoginDetailsResponse returns information regarding the Console authentication mechanism.
|
||||
func getLoginDetailsResponse() (*models.LoginDetails, *models.Error) {
|
||||
loginStrategy := models.LoginDetailsLoginStrategyServiceDashAccount
|
||||
@@ -151,22 +114,48 @@ func getLoginDetailsResponse() (*models.LoginDetails, *models.Error) {
|
||||
return loginDetails, nil
|
||||
}
|
||||
|
||||
func getLoginOauth2AuthResponse() (*models.LoginResponse, *models.Error) {
|
||||
// verifyUserAgainstIDP will verify user identity against the configured IDP and return MinIO credentials
|
||||
func verifyUserAgainstIDP(ctx context.Context, provider auth.IdentityProviderI, code, state string) (*xoauth2.Token, error) {
|
||||
oauth2Token, err := provider.VerifyIdentityForOperator(ctx, code, state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return oauth2Token, nil
|
||||
}
|
||||
|
||||
creds, err := newConsoleCredentials(getK8sSAToken())
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
func getLoginOauth2AuthResponse(lr *models.LoginOauth2AuthRequest) (*models.LoginResponse, *models.Error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
||||
defer cancel()
|
||||
if oauth2.IsIDPEnabled() {
|
||||
// initialize new oauth2 client
|
||||
oauth2Client, err := oauth2.NewOauth2ProviderClient(nil, restapi.GetConsoleHTTPClient())
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// initialize new identity provider
|
||||
identityProvider := auth.IdentityProvider{Client: oauth2Client}
|
||||
// Validate user against IDP
|
||||
_, err = verifyUserAgainstIDP(ctx, identityProvider, *lr.Code, *lr.State)
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// If we pass here that means the IDP correctly authenticate the user with the operator resource
|
||||
// we proceed to use the service account token configured in the operator-console pod
|
||||
creds, err := newConsoleCredentials(getK8sSAToken())
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
token, err := login(restapi.ConsoleCredentials{ConsoleCredentials: creds})
|
||||
if err != nil {
|
||||
return nil, prepareError(errInvalidCredentials, nil, err)
|
||||
}
|
||||
// serialize output
|
||||
loginResponse := &models.LoginResponse{
|
||||
SessionID: *token,
|
||||
}
|
||||
return loginResponse, nil
|
||||
}
|
||||
consoleCredentials := restapi.ConsoleCredentials{ConsoleCredentials: creds}
|
||||
token, err := login(consoleCredentials)
|
||||
if err != nil {
|
||||
return nil, prepareError(errInvalidCredentials, nil, err)
|
||||
}
|
||||
// serialize output
|
||||
loginResponse := &models.LoginResponse{
|
||||
SessionID: *token,
|
||||
}
|
||||
return loginResponse, nil
|
||||
return nil, prepareError(errorGeneric)
|
||||
}
|
||||
|
||||
func newConsoleCredentials(secretKey string) (*credentials.Credentials, error) {
|
||||
|
||||
@@ -20,8 +20,8 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/minio/console/pkg/auth/idp/oauth2"
|
||||
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
xoauth2 "golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// IdentityProviderI interface with all functions to be implemented
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
// that are used within this project.
|
||||
type IdentityProviderI interface {
|
||||
VerifyIdentity(ctx context.Context, code, state string) (*credentials.Credentials, error)
|
||||
VerifyIdentityForOperator(ctx context.Context, code, state string) (*xoauth2.Token, error)
|
||||
GenerateLoginURL() string
|
||||
}
|
||||
|
||||
@@ -45,6 +46,11 @@ func (c IdentityProvider) VerifyIdentity(ctx context.Context, code, state string
|
||||
return c.Client.VerifyIdentity(ctx, code, state)
|
||||
}
|
||||
|
||||
// VerifyIdentityForOperator will verify the user identity against the idp using the authorization code flow
|
||||
func (c IdentityProvider) VerifyIdentityForOperator(ctx context.Context, code, state string) (*xoauth2.Token, error) {
|
||||
return c.Client.VerifyIdentityForOperator(ctx, code, state)
|
||||
}
|
||||
|
||||
// GenerateLoginURL returns a new URL used by the user to login against the idp
|
||||
func (c IdentityProvider) GenerateLoginURL() string {
|
||||
return c.Client.GenerateLoginURL()
|
||||
|
||||
@@ -181,7 +181,8 @@ type User struct {
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// VerifyIdentity will contact the configured IDP and validate the user identity based on the authorization code
|
||||
// VerifyIdentity will contact the configured IDP to the user identity based on the authorization code and state
|
||||
// if the user is valid, then it will contact MinIO to get valid sts credentials based on the identity provided by the IDP
|
||||
func (client *Provider) VerifyIdentity(ctx context.Context, code, state string) (*credentials.Credentials, error) {
|
||||
// verify the provided state is valid (prevents CSRF attacks)
|
||||
if err := validateOauth2State(state); err != nil {
|
||||
@@ -232,6 +233,23 @@ func (client *Provider) VerifyIdentity(ctx context.Context, code, state string)
|
||||
return sts, nil
|
||||
}
|
||||
|
||||
// VerifyIdentityForOperator will contact the configured IDP and validate the user identity based on the authorization code and state
|
||||
func (client *Provider) VerifyIdentityForOperator(ctx context.Context, code, state string) (*xoauth2.Token, error) {
|
||||
// verify the provided state is valid (prevents CSRF attacks)
|
||||
if err := validateOauth2State(state); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
customCtx := context.WithValue(ctx, oauth2.HTTPClient, client.provHTTPClient)
|
||||
oauth2Token, err := client.oauth2Config.Exchange(customCtx, code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !oauth2Token.Valid() {
|
||||
return nil, errors.New("invalid token")
|
||||
}
|
||||
return oauth2Token, nil
|
||||
}
|
||||
|
||||
// validateOauth2State validates the provided state was originated using the same
|
||||
// instance (or one configured using the same secrets) of Console, this is basically used to prevent CSRF attacks
|
||||
// https://security.stackexchange.com/questions/20187/oauth2-cross-site-request-forgery-and-state-parameter
|
||||
|
||||
@@ -28,7 +28,7 @@ export class API {
|
||||
.then((res) => res.body)
|
||||
.catch((err) => {
|
||||
// if we get unauthorized, kick out the user
|
||||
if (err.status === 401) {
|
||||
if (err.status === 401 && localStorage.getItem("userLoggedIn")) {
|
||||
if (window.location.pathname !== "/") {
|
||||
localStorage.setItem("redirect-path", window.location.pathname);
|
||||
}
|
||||
|
||||
@@ -20,9 +20,14 @@ import { SvgIcon, SvgIconProps } from "@mui/material";
|
||||
const PrometheusIcon = (props: SvgIconProps) => {
|
||||
return (
|
||||
<SvgIcon {...props}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 27.999">
|
||||
<path id="prometheus-icon" d="M14,.667a14,14,0,1,0,14,14A14,14,0,0,0,14,.667Zm0,26.2c-2.2,0-3.983-1.469-3.983-3.282h7.967C17.983,25.4,16.2,26.869,14,26.869ZM20.579,22.5H7.42V20.114H20.58V22.5h0Zm-.047-3.614H7.458c-.044-.05-.088-.1-.13-.15a9.536,9.536,0,0,1-1.972-3.36c-.005-.029,1.633.335,2.8.6,0,0,.6.138,1.472.3a5.463,5.463,0,0,1-1.338-3.513c0-2.806,2.153-5.259,1.376-7.241.756.061,1.564,1.6,1.619,3.993a8.574,8.574,0,0,0,1.14-4.381c0-1.287.848-2.783,1.7-2.834-.756,1.246.2,2.315,1.042,4.966.317,1,.277,2.671.522,3.734.081-2.207.461-5.427,1.861-6.539-.618,1.4.091,3.152.576,3.994a7.568,7.568,0,0,1,1.257,4.335,5.416,5.416,0,0,1-1.3,3.5c.924-.173,1.563-.33,1.563-.33l3-.586A8.512,8.512,0,0,1,20.532,18.886Z" transform="translate(0 -0.667)" fill="#07193e"/>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 27.999">
|
||||
<path
|
||||
id="prometheus-icon"
|
||||
d="M14,.667a14,14,0,1,0,14,14A14,14,0,0,0,14,.667Zm0,26.2c-2.2,0-3.983-1.469-3.983-3.282h7.967C17.983,25.4,16.2,26.869,14,26.869ZM20.579,22.5H7.42V20.114H20.58V22.5h0Zm-.047-3.614H7.458c-.044-.05-.088-.1-.13-.15a9.536,9.536,0,0,1-1.972-3.36c-.005-.029,1.633.335,2.8.6,0,0,.6.138,1.472.3a5.463,5.463,0,0,1-1.338-3.513c0-2.806,2.153-5.259,1.376-7.241.756.061,1.564,1.6,1.619,3.993a8.574,8.574,0,0,0,1.14-4.381c0-1.287.848-2.783,1.7-2.834-.756,1.246.2,2.315,1.042,4.966.317,1,.277,2.671.522,3.734.081-2.207.461-5.427,1.861-6.539-.618,1.4.091,3.152.576,3.994a7.568,7.568,0,0,1,1.257,4.335,5.416,5.416,0,0,1-1.3,3.5c.924-.173,1.563-.33,1.563-.33l3-.586A8.512,8.512,0,0,1,20.532,18.886Z"
|
||||
transform="translate(0 -0.667)"
|
||||
fill="#07193e"
|
||||
/>
|
||||
</svg>
|
||||
</SvgIcon>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -92,7 +92,7 @@ const ChangePassword = ({
|
||||
|
||||
api
|
||||
.invoke("POST", "/api/v1/account/change-password", request)
|
||||
.then((res) => {
|
||||
.then(() => {
|
||||
setLoading(false);
|
||||
setNewPassword("");
|
||||
setReNewPassword("");
|
||||
|
||||
@@ -31,7 +31,6 @@ import { Usage } from "./types";
|
||||
import { setErrorSnackMessage } from "../../../actions";
|
||||
import { ErrorResponseHandler } from "../../../common/types";
|
||||
|
||||
|
||||
interface IDashboardSimple {
|
||||
classes: any;
|
||||
displayErrorMessage: typeof setErrorSnackMessage;
|
||||
@@ -89,7 +88,6 @@ const Dashboard = ({ classes, displayErrorMessage }: IDashboardSimple) => {
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -14,31 +14,191 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { FC, useEffect, useState } from "react"; // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
import { RouteComponentProps } from "react-router";
|
||||
import storage from "local-storage-fallback";
|
||||
import React, { useEffect, useState } from "react"; // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
import api from "../../common/api";
|
||||
import { setErrorSnackMessage } from "../../actions";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import history from "../../history";
|
||||
import { Paper } from "@mui/material";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
|
||||
|
||||
const LoginCallback: FC<RouteComponentProps> = ({ location }) => {
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
"@global": {
|
||||
body: {
|
||||
backgroundColor: "#FAFAFA",
|
||||
},
|
||||
},
|
||||
paper: {
|
||||
borderRadius: 8,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
width: 800,
|
||||
height: 424,
|
||||
margin: "auto",
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
marginLeft: -400,
|
||||
marginTop: -212,
|
||||
"&.MuiPaper-root": {
|
||||
borderRadius: 8,
|
||||
},
|
||||
},
|
||||
avatar: {
|
||||
margin: theme.spacing(1),
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
},
|
||||
form: {
|
||||
width: "100%", // Fix IE 11 issue.
|
||||
},
|
||||
submit: {
|
||||
margin: "30px 0px 16px",
|
||||
height: 40,
|
||||
boxShadow: "none",
|
||||
padding: "16px 30px",
|
||||
},
|
||||
errorBlock: {
|
||||
backgroundColor: "#C72C48",
|
||||
width: 800,
|
||||
height: 64,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: "absolute",
|
||||
left: "50%",
|
||||
top: "50%",
|
||||
marginLeft: -400,
|
||||
marginTop: -290,
|
||||
color: "#fff",
|
||||
fontWeight: 700,
|
||||
fontSize: 14,
|
||||
borderRadius: 8,
|
||||
padding: 10,
|
||||
boxSizing: "border-box",
|
||||
},
|
||||
mainContainer: {
|
||||
position: "relative",
|
||||
height: 424,
|
||||
},
|
||||
theOcean: {
|
||||
borderTopLeftRadius: 8,
|
||||
borderBottomLeftRadius: 8,
|
||||
background:
|
||||
"transparent linear-gradient(to bottom, #073052 0%,#05122b 100%); 0% 0% no-repeat padding-box;",
|
||||
},
|
||||
oceanBg: {
|
||||
backgroundImage: "url(/images/BG_Illustration.svg)",
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundPosition: "bottom left",
|
||||
height: "100%",
|
||||
width: 324,
|
||||
},
|
||||
theLogin: {
|
||||
padding: "40px 45px 20px 45px",
|
||||
},
|
||||
loadingLoginStrategy: {
|
||||
textAlign: "center",
|
||||
},
|
||||
headerTitle: {
|
||||
marginBottom: 10,
|
||||
},
|
||||
submitContainer: {
|
||||
textAlign: "right",
|
||||
},
|
||||
disclaimer: {
|
||||
fontSize: 12,
|
||||
marginTop: 30,
|
||||
},
|
||||
jwtInput: {
|
||||
marginTop: 45,
|
||||
},
|
||||
linearPredef: {
|
||||
height: 10,
|
||||
},
|
||||
errorIconStyle: {
|
||||
marginRight: 3,
|
||||
},
|
||||
loaderAlignment: {
|
||||
display: "flex",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
flexDirection: "column",
|
||||
},
|
||||
retryButton: {
|
||||
alignSelf: "flex-end",
|
||||
},
|
||||
extraDetailsContainer: {
|
||||
fontStyle: "italic",
|
||||
color: "#9C9C9C",
|
||||
transition: "all .2s ease-in-out",
|
||||
padding: "0 5px",
|
||||
marginTop: 5,
|
||||
overflow: "auto",
|
||||
},
|
||||
errorLabel: {
|
||||
color: "#000",
|
||||
fontSize: 18,
|
||||
fontWeight: 500,
|
||||
marginLeft: 5,
|
||||
},
|
||||
simpleError: {
|
||||
marginTop: 5,
|
||||
padding: "2px 5px",
|
||||
fontSize: 16,
|
||||
color: "#000",
|
||||
},
|
||||
messageIcon: {
|
||||
color: "#C72C48",
|
||||
display: "flex",
|
||||
"& svg": {
|
||||
width: 32,
|
||||
height: 32,
|
||||
},
|
||||
},
|
||||
errorTitle: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
},
|
||||
});
|
||||
|
||||
interface ILoginCallBackProps {
|
||||
setErrorSnackMessage: typeof setErrorSnackMessage;
|
||||
classes: any;
|
||||
}
|
||||
|
||||
const LoginCallback = ({
|
||||
classes,
|
||||
setErrorSnackMessage,
|
||||
}: ILoginCallBackProps) => {
|
||||
const [error, setError] = useState<string>("");
|
||||
const [errorDescription, setErrorDescription] = useState<string>("");
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
|
||||
useEffect(() => {
|
||||
const code = (location.search.match(/code=([^&]+)/) || [])[1];
|
||||
const state = (location.search.match(/state=([^&]+)/) || [])[1];
|
||||
const error = (location.search.match(/error=([^&]+)/) || [])[1];
|
||||
const errorDescription = (location.search.match(
|
||||
/error_description=([^&]+)/
|
||||
) || [])[1];
|
||||
if (error !== undefined || errorDescription !== undefined) {
|
||||
setError(error);
|
||||
setErrorDescription(errorDescription);
|
||||
} else {
|
||||
api
|
||||
.invoke("POST", "/api/v1/login/oauth2/auth", { code, state })
|
||||
.then((res: any) => {
|
||||
if (res && res.sessionId) {
|
||||
// store the jwt token
|
||||
storage.setItem("token", res.sessionId);
|
||||
if (loading) {
|
||||
const queryString = window.location.search;
|
||||
const urlParams = new URLSearchParams(queryString);
|
||||
const code = urlParams.get("code");
|
||||
const state = urlParams.get("state");
|
||||
const error = urlParams.get("error");
|
||||
const errorDescription = urlParams.get("errorDescription");
|
||||
if (error || errorDescription) {
|
||||
setError(error || "");
|
||||
setErrorDescription(errorDescription || "");
|
||||
setLoading(false);
|
||||
} else {
|
||||
api
|
||||
.invoke("POST", "/api/v1/login/oauth2/auth", { code, state })
|
||||
.then(() => {
|
||||
// We push to history the new URL.
|
||||
let targetPath = "/";
|
||||
if (
|
||||
@@ -48,22 +208,55 @@ const LoginCallback: FC<RouteComponentProps> = ({ location }) => {
|
||||
targetPath = `${localStorage.getItem("redirect-path")}`;
|
||||
localStorage.setItem("redirect-path", "");
|
||||
}
|
||||
window.location.href = targetPath;
|
||||
}
|
||||
})
|
||||
.catch((res: any) => {
|
||||
window.location.href = "/login";
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
setLoading(false);
|
||||
history.push(targetPath);
|
||||
})
|
||||
.catch((error) => {
|
||||
setError(error.errorMessage);
|
||||
setErrorDescription(error.detailedError);
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [location.search]);
|
||||
}, [loading]);
|
||||
return error !== "" || errorDescription !== "" ? (
|
||||
<div>
|
||||
<h2>IDP Error:</h2>
|
||||
<p>{error}</p>
|
||||
<p>{errorDescription}</p>
|
||||
</div>
|
||||
<React.Fragment>
|
||||
<Paper className={classes.paper}>
|
||||
<Grid container className={classes.mainContainer}>
|
||||
<Grid item xs={7} className={classes.theOcean}>
|
||||
<div className={classes.oceanBg} />
|
||||
</Grid>
|
||||
<Grid item xs={5} className={classes.theLogin}>
|
||||
<div className={classes.errorTitle}>
|
||||
<span className={classes.messageIcon}>
|
||||
<ErrorOutlineIcon />
|
||||
</span>
|
||||
<span className={classes.errorLabel}>Error from IDP</span>
|
||||
</div>
|
||||
<div className={classes.simpleError}>{error}</div>
|
||||
<Typography
|
||||
variant="body1"
|
||||
gutterBottom
|
||||
component="div"
|
||||
className={classes.extraDetailsContainer}
|
||||
>
|
||||
{errorDescription}
|
||||
</Typography>
|
||||
<Button
|
||||
component={"a"}
|
||||
href="/login"
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
className={classes.submit}
|
||||
>
|
||||
Back to Login
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Paper>
|
||||
</React.Fragment>
|
||||
) : null;
|
||||
};
|
||||
|
||||
export default LoginCallback;
|
||||
export default withStyles(styles)(LoginCallback);
|
||||
|
||||
@@ -70,11 +70,8 @@ func init() {
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
"204": {
|
||||
"description": "A successful login."
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
@@ -2324,11 +2321,8 @@ func init() {
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
"204": {
|
||||
"description": "A successful login."
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
@@ -2358,45 +2352,8 @@ func init() {
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/login/operator": {
|
||||
"post": {
|
||||
"security": [],
|
||||
"tags": [
|
||||
"UserAPI"
|
||||
],
|
||||
"summary": "Login to Operator Console.",
|
||||
"operationId": "LoginOperator",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginOperatorRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
"204": {
|
||||
"description": "A successful login."
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
@@ -2412,7 +2369,7 @@ func init() {
|
||||
"tags": [
|
||||
"UserAPI"
|
||||
],
|
||||
"summary": "Logout from Operator.",
|
||||
"summary": "Logout from Console.",
|
||||
"operationId": "Logout",
|
||||
"responses": {
|
||||
"200": {
|
||||
@@ -4482,17 +4439,6 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"loginOperatorRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"jwt"
|
||||
],
|
||||
"properties": {
|
||||
"jwt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"loginRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -5771,11 +5717,8 @@ func init() {
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
"204": {
|
||||
"description": "A successful login."
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
@@ -8025,11 +7968,8 @@ func init() {
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
"204": {
|
||||
"description": "A successful login."
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
@@ -8059,45 +7999,8 @@ func init() {
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/login/operator": {
|
||||
"post": {
|
||||
"security": [],
|
||||
"tags": [
|
||||
"UserAPI"
|
||||
],
|
||||
"summary": "Login to Operator Console.",
|
||||
"operationId": "LoginOperator",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginOperatorRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
"204": {
|
||||
"description": "A successful login."
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
@@ -8113,7 +8016,7 @@ func init() {
|
||||
"tags": [
|
||||
"UserAPI"
|
||||
],
|
||||
"summary": "Logout from Operator.",
|
||||
"summary": "Logout from Console.",
|
||||
"operationId": "Logout",
|
||||
"responses": {
|
||||
"200": {
|
||||
@@ -10303,17 +10206,6 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"loginOperatorRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"jwt"
|
||||
],
|
||||
"properties": {
|
||||
"jwt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"loginRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
||||
@@ -14,6 +14,7 @@ var (
|
||||
// ErrorGeneric is a generic error message
|
||||
ErrorGeneric = errors.New("an error occurred, please try again")
|
||||
errInvalidCredentials = errors.New("invalid Login")
|
||||
errForbidden = errors.New("403 Forbidden")
|
||||
errorGenericInvalidSession = errors.New("invalid session")
|
||||
// ErrorGenericNotFound Generic error for not found
|
||||
ErrorGenericNotFound = errors.New("not found")
|
||||
@@ -54,6 +55,9 @@ func prepareError(err ...error) *models.Error {
|
||||
frame := getFrame(2)
|
||||
fileParts := strings.Split(frame.File, "/")
|
||||
LogError("original error -> (%s:%d: %v)", fileParts[len(fileParts)-1], frame.Line, err[0])
|
||||
if err[0].Error() == errForbidden.Error() {
|
||||
errorCode = 403
|
||||
}
|
||||
if err[0] == ErrorGenericNotFound {
|
||||
errorCode = 404
|
||||
errorMessage = ErrorGenericNotFound.Error()
|
||||
|
||||
@@ -263,9 +263,6 @@ func NewConsoleAPI(spec *loads.Document) *ConsoleAPI {
|
||||
UserAPILoginOauth2AuthHandler: user_api.LoginOauth2AuthHandlerFunc(func(params user_api.LoginOauth2AuthParams) middleware.Responder {
|
||||
return middleware.NotImplemented("operation user_api.LoginOauth2Auth has not yet been implemented")
|
||||
}),
|
||||
UserAPILoginOperatorHandler: user_api.LoginOperatorHandlerFunc(func(params user_api.LoginOperatorParams) middleware.Responder {
|
||||
return middleware.NotImplemented("operation user_api.LoginOperator has not yet been implemented")
|
||||
}),
|
||||
UserAPILogoutHandler: user_api.LogoutHandlerFunc(func(params user_api.LogoutParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation user_api.Logout has not yet been implemented")
|
||||
}),
|
||||
@@ -549,8 +546,6 @@ type ConsoleAPI struct {
|
||||
UserAPILoginDetailHandler user_api.LoginDetailHandler
|
||||
// UserAPILoginOauth2AuthHandler sets the operation handler for the login oauth2 auth operation
|
||||
UserAPILoginOauth2AuthHandler user_api.LoginOauth2AuthHandler
|
||||
// UserAPILoginOperatorHandler sets the operation handler for the login operator operation
|
||||
UserAPILoginOperatorHandler user_api.LoginOperatorHandler
|
||||
// UserAPILogoutHandler sets the operation handler for the logout operation
|
||||
UserAPILogoutHandler user_api.LogoutHandler
|
||||
// UserAPIMakeBucketHandler sets the operation handler for the make bucket operation
|
||||
@@ -900,9 +895,6 @@ func (o *ConsoleAPI) Validate() error {
|
||||
if o.UserAPILoginOauth2AuthHandler == nil {
|
||||
unregistered = append(unregistered, "user_api.LoginOauth2AuthHandler")
|
||||
}
|
||||
if o.UserAPILoginOperatorHandler == nil {
|
||||
unregistered = append(unregistered, "user_api.LoginOperatorHandler")
|
||||
}
|
||||
if o.UserAPILogoutHandler == nil {
|
||||
unregistered = append(unregistered, "user_api.LogoutHandler")
|
||||
}
|
||||
@@ -1368,10 +1360,6 @@ func (o *ConsoleAPI) initHandlerCache() {
|
||||
if o.handlers["POST"] == nil {
|
||||
o.handlers["POST"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["POST"]["/login/operator"] = user_api.NewLoginOperator(o.context, o.UserAPILoginOperatorHandler)
|
||||
if o.handlers["POST"] == nil {
|
||||
o.handlers["POST"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["POST"]["/logout"] = user_api.NewLogout(o.context, o.UserAPILogoutHandler)
|
||||
if o.handlers["POST"] == nil {
|
||||
o.handlers["POST"] = make(map[string]http.Handler)
|
||||
|
||||
@@ -30,48 +30,28 @@ import (
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// AccountChangePasswordCreatedCode is the HTTP code returned for type AccountChangePasswordCreated
|
||||
const AccountChangePasswordCreatedCode int = 201
|
||||
// AccountChangePasswordNoContentCode is the HTTP code returned for type AccountChangePasswordNoContent
|
||||
const AccountChangePasswordNoContentCode int = 204
|
||||
|
||||
/*AccountChangePasswordCreated A successful login.
|
||||
/*AccountChangePasswordNoContent A successful login.
|
||||
|
||||
swagger:response accountChangePasswordCreated
|
||||
swagger:response accountChangePasswordNoContent
|
||||
*/
|
||||
type AccountChangePasswordCreated struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.LoginResponse `json:"body,omitempty"`
|
||||
type AccountChangePasswordNoContent struct {
|
||||
}
|
||||
|
||||
// NewAccountChangePasswordCreated creates AccountChangePasswordCreated with default headers values
|
||||
func NewAccountChangePasswordCreated() *AccountChangePasswordCreated {
|
||||
// NewAccountChangePasswordNoContent creates AccountChangePasswordNoContent with default headers values
|
||||
func NewAccountChangePasswordNoContent() *AccountChangePasswordNoContent {
|
||||
|
||||
return &AccountChangePasswordCreated{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the account change password created response
|
||||
func (o *AccountChangePasswordCreated) WithPayload(payload *models.LoginResponse) *AccountChangePasswordCreated {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the account change password created response
|
||||
func (o *AccountChangePasswordCreated) SetPayload(payload *models.LoginResponse) {
|
||||
o.Payload = payload
|
||||
return &AccountChangePasswordNoContent{}
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *AccountChangePasswordCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
func (o *AccountChangePasswordNoContent) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(201)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
|
||||
|
||||
rw.WriteHeader(204)
|
||||
}
|
||||
|
||||
/*AccountChangePasswordDefault Generic error response.
|
||||
|
||||
@@ -30,48 +30,28 @@ import (
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// LoginOauth2AuthCreatedCode is the HTTP code returned for type LoginOauth2AuthCreated
|
||||
const LoginOauth2AuthCreatedCode int = 201
|
||||
// LoginOauth2AuthNoContentCode is the HTTP code returned for type LoginOauth2AuthNoContent
|
||||
const LoginOauth2AuthNoContentCode int = 204
|
||||
|
||||
/*LoginOauth2AuthCreated A successful login.
|
||||
/*LoginOauth2AuthNoContent A successful login.
|
||||
|
||||
swagger:response loginOauth2AuthCreated
|
||||
swagger:response loginOauth2AuthNoContent
|
||||
*/
|
||||
type LoginOauth2AuthCreated struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.LoginResponse `json:"body,omitempty"`
|
||||
type LoginOauth2AuthNoContent struct {
|
||||
}
|
||||
|
||||
// NewLoginOauth2AuthCreated creates LoginOauth2AuthCreated with default headers values
|
||||
func NewLoginOauth2AuthCreated() *LoginOauth2AuthCreated {
|
||||
// NewLoginOauth2AuthNoContent creates LoginOauth2AuthNoContent with default headers values
|
||||
func NewLoginOauth2AuthNoContent() *LoginOauth2AuthNoContent {
|
||||
|
||||
return &LoginOauth2AuthCreated{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the login oauth2 auth created response
|
||||
func (o *LoginOauth2AuthCreated) WithPayload(payload *models.LoginResponse) *LoginOauth2AuthCreated {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the login oauth2 auth created response
|
||||
func (o *LoginOauth2AuthCreated) SetPayload(payload *models.LoginResponse) {
|
||||
o.Payload = payload
|
||||
return &LoginOauth2AuthNoContent{}
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *LoginOauth2AuthCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
func (o *LoginOauth2AuthNoContent) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(201)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
|
||||
|
||||
rw.WriteHeader(204)
|
||||
}
|
||||
|
||||
/*LoginOauth2AuthDefault Generic error response.
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package user_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
)
|
||||
|
||||
// LoginOperatorHandlerFunc turns a function with the right signature into a login operator handler
|
||||
type LoginOperatorHandlerFunc func(LoginOperatorParams) middleware.Responder
|
||||
|
||||
// Handle executing the request and returning a response
|
||||
func (fn LoginOperatorHandlerFunc) Handle(params LoginOperatorParams) middleware.Responder {
|
||||
return fn(params)
|
||||
}
|
||||
|
||||
// LoginOperatorHandler interface for that can handle valid login operator params
|
||||
type LoginOperatorHandler interface {
|
||||
Handle(LoginOperatorParams) middleware.Responder
|
||||
}
|
||||
|
||||
// NewLoginOperator creates a new http.Handler for the login operator operation
|
||||
func NewLoginOperator(ctx *middleware.Context, handler LoginOperatorHandler) *LoginOperator {
|
||||
return &LoginOperator{Context: ctx, Handler: handler}
|
||||
}
|
||||
|
||||
/* LoginOperator swagger:route POST /login/operator UserAPI loginOperator
|
||||
|
||||
Login to Operator Console.
|
||||
|
||||
*/
|
||||
type LoginOperator struct {
|
||||
Context *middleware.Context
|
||||
Handler LoginOperatorHandler
|
||||
}
|
||||
|
||||
func (o *LoginOperator) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||
if rCtx != nil {
|
||||
*r = *rCtx
|
||||
}
|
||||
var Params = NewLoginOperatorParams()
|
||||
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
|
||||
o.Context.Respond(rw, r, route.Produces, route, err)
|
||||
return
|
||||
}
|
||||
|
||||
res := o.Handler.Handle(Params) // actually handle the request
|
||||
o.Context.Respond(rw, r, route.Produces, route, res)
|
||||
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package user_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/validate"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// NewLoginOperatorParams creates a new LoginOperatorParams object
|
||||
//
|
||||
// There are no default values defined in the spec.
|
||||
func NewLoginOperatorParams() LoginOperatorParams {
|
||||
|
||||
return LoginOperatorParams{}
|
||||
}
|
||||
|
||||
// LoginOperatorParams contains all the bound params for the login operator operation
|
||||
// typically these are obtained from a http.Request
|
||||
//
|
||||
// swagger:parameters LoginOperator
|
||||
type LoginOperatorParams struct {
|
||||
|
||||
// HTTP Request Object
|
||||
HTTPRequest *http.Request `json:"-"`
|
||||
|
||||
/*
|
||||
Required: true
|
||||
In: body
|
||||
*/
|
||||
Body *models.LoginOperatorRequest
|
||||
}
|
||||
|
||||
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
|
||||
// for simple values it will use straight method calls.
|
||||
//
|
||||
// To ensure default values, the struct must have been initialized with NewLoginOperatorParams() beforehand.
|
||||
func (o *LoginOperatorParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||
var res []error
|
||||
|
||||
o.HTTPRequest = r
|
||||
|
||||
if runtime.HasBody(r) {
|
||||
defer r.Body.Close()
|
||||
var body models.LoginOperatorRequest
|
||||
if err := route.Consumer.Consume(r.Body, &body); err != nil {
|
||||
if err == io.EOF {
|
||||
res = append(res, errors.Required("body", "body", ""))
|
||||
} else {
|
||||
res = append(res, errors.NewParseError("body", "body", "", err))
|
||||
}
|
||||
} else {
|
||||
// validate body object
|
||||
if err := body.Validate(route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
ctx := validate.WithOperationRequest(context.Background())
|
||||
if err := body.ContextValidate(ctx, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) == 0 {
|
||||
o.Body = &body
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = append(res, errors.Required("body", "body", ""))
|
||||
}
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package user_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// LoginOperatorCreatedCode is the HTTP code returned for type LoginOperatorCreated
|
||||
const LoginOperatorCreatedCode int = 201
|
||||
|
||||
/*LoginOperatorCreated A successful login.
|
||||
|
||||
swagger:response loginOperatorCreated
|
||||
*/
|
||||
type LoginOperatorCreated struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.LoginResponse `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewLoginOperatorCreated creates LoginOperatorCreated with default headers values
|
||||
func NewLoginOperatorCreated() *LoginOperatorCreated {
|
||||
|
||||
return &LoginOperatorCreated{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the login operator created response
|
||||
func (o *LoginOperatorCreated) WithPayload(payload *models.LoginResponse) *LoginOperatorCreated {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the login operator created response
|
||||
func (o *LoginOperatorCreated) SetPayload(payload *models.LoginResponse) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *LoginOperatorCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(201)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*LoginOperatorDefault Generic error response.
|
||||
|
||||
swagger:response loginOperatorDefault
|
||||
*/
|
||||
type LoginOperatorDefault struct {
|
||||
_statusCode int
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.Error `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewLoginOperatorDefault creates LoginOperatorDefault with default headers values
|
||||
func NewLoginOperatorDefault(code int) *LoginOperatorDefault {
|
||||
if code <= 0 {
|
||||
code = 500
|
||||
}
|
||||
|
||||
return &LoginOperatorDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
// WithStatusCode adds the status to the login operator default response
|
||||
func (o *LoginOperatorDefault) WithStatusCode(code int) *LoginOperatorDefault {
|
||||
o._statusCode = code
|
||||
return o
|
||||
}
|
||||
|
||||
// SetStatusCode sets the status to the login operator default response
|
||||
func (o *LoginOperatorDefault) SetStatusCode(code int) {
|
||||
o._statusCode = code
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the login operator default response
|
||||
func (o *LoginOperatorDefault) WithPayload(payload *models.Error) *LoginOperatorDefault {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the login operator default response
|
||||
func (o *LoginOperatorDefault) SetPayload(payload *models.Error) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *LoginOperatorDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(o._statusCode)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package user_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the generate command
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
golangswaggerpaths "path"
|
||||
)
|
||||
|
||||
// LoginOperatorURL generates an URL for the login operator operation
|
||||
type LoginOperatorURL struct {
|
||||
_basePath string
|
||||
}
|
||||
|
||||
// WithBasePath sets the base path for this url builder, only required when it's different from the
|
||||
// base path specified in the swagger spec.
|
||||
// When the value of the base path is an empty string
|
||||
func (o *LoginOperatorURL) WithBasePath(bp string) *LoginOperatorURL {
|
||||
o.SetBasePath(bp)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetBasePath sets the base path for this url builder, only required when it's different from the
|
||||
// base path specified in the swagger spec.
|
||||
// When the value of the base path is an empty string
|
||||
func (o *LoginOperatorURL) SetBasePath(bp string) {
|
||||
o._basePath = bp
|
||||
}
|
||||
|
||||
// Build a url path and query string
|
||||
func (o *LoginOperatorURL) Build() (*url.URL, error) {
|
||||
var _result url.URL
|
||||
|
||||
var _path = "/login/operator"
|
||||
|
||||
_basePath := o._basePath
|
||||
if _basePath == "" {
|
||||
_basePath = "/api/v1"
|
||||
}
|
||||
_result.Path = golangswaggerpaths.Join(_basePath, _path)
|
||||
|
||||
return &_result, nil
|
||||
}
|
||||
|
||||
// Must is a helper function to panic when the url builder returns an error
|
||||
func (o *LoginOperatorURL) Must(u *url.URL, err error) *url.URL {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if u == nil {
|
||||
panic("url can't be nil")
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
// String returns the string representation of the path with query string
|
||||
func (o *LoginOperatorURL) String() string {
|
||||
return o.Must(o.Build()).String()
|
||||
}
|
||||
|
||||
// BuildFull builds a full url with scheme, host, path and query string
|
||||
func (o *LoginOperatorURL) BuildFull(scheme, host string) (*url.URL, error) {
|
||||
if scheme == "" {
|
||||
return nil, errors.New("scheme is required for a full url on LoginOperatorURL")
|
||||
}
|
||||
if host == "" {
|
||||
return nil, errors.New("host is required for a full url on LoginOperatorURL")
|
||||
}
|
||||
|
||||
base, err := o.Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
base.Scheme = scheme
|
||||
base.Host = host
|
||||
return base, nil
|
||||
}
|
||||
|
||||
// StringFull returns the string representation of a complete url
|
||||
func (o *LoginOperatorURL) StringFull(scheme, host string) string {
|
||||
return o.Must(o.BuildFull(scheme, host)).String()
|
||||
}
|
||||
@@ -30,48 +30,28 @@ import (
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// LoginCreatedCode is the HTTP code returned for type LoginCreated
|
||||
const LoginCreatedCode int = 201
|
||||
// LoginNoContentCode is the HTTP code returned for type LoginNoContent
|
||||
const LoginNoContentCode int = 204
|
||||
|
||||
/*LoginCreated A successful login.
|
||||
/*LoginNoContent A successful login.
|
||||
|
||||
swagger:response loginCreated
|
||||
swagger:response loginNoContent
|
||||
*/
|
||||
type LoginCreated struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.LoginResponse `json:"body,omitempty"`
|
||||
type LoginNoContent struct {
|
||||
}
|
||||
|
||||
// NewLoginCreated creates LoginCreated with default headers values
|
||||
func NewLoginCreated() *LoginCreated {
|
||||
// NewLoginNoContent creates LoginNoContent with default headers values
|
||||
func NewLoginNoContent() *LoginNoContent {
|
||||
|
||||
return &LoginCreated{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the login created response
|
||||
func (o *LoginCreated) WithPayload(payload *models.LoginResponse) *LoginCreated {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the login created response
|
||||
func (o *LoginCreated) SetPayload(payload *models.LoginResponse) {
|
||||
o.Payload = payload
|
||||
return &LoginNoContent{}
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *LoginCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
func (o *LoginNoContent) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(201)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
|
||||
|
||||
rw.WriteHeader(204)
|
||||
}
|
||||
|
||||
/*LoginDefault Generic error response.
|
||||
|
||||
@@ -50,7 +50,7 @@ func NewLogout(ctx *middleware.Context, handler LogoutHandler) *Logout {
|
||||
|
||||
/* Logout swagger:route POST /logout UserAPI logout
|
||||
|
||||
Logout from Operator.
|
||||
Logout from Console.
|
||||
|
||||
*/
|
||||
type Logout struct {
|
||||
|
||||
@@ -41,7 +41,7 @@ func registerAccountHandlers(api *operations.ConsoleAPI) {
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
|
||||
cookie := NewSessionCookieForConsole(changePasswordResponse.SessionID)
|
||||
http.SetCookie(w, &cookie)
|
||||
user_api.NewLoginCreated().WithPayload(changePasswordResponse).WriteResponse(w, p)
|
||||
user_api.NewLoginNoContent().WriteResponse(w, p)
|
||||
})
|
||||
})
|
||||
// Checks if user can perform an action
|
||||
|
||||
@@ -36,7 +36,7 @@ import (
|
||||
)
|
||||
|
||||
func registerLoginHandlers(api *operations.ConsoleAPI) {
|
||||
// get login strategy
|
||||
// GET login strategy
|
||||
api.UserAPILoginDetailHandler = user_api.LoginDetailHandlerFunc(func(params user_api.LoginDetailParams) middleware.Responder {
|
||||
loginDetails, err := getLoginDetailsResponse()
|
||||
if err != nil {
|
||||
@@ -44,7 +44,7 @@ func registerLoginHandlers(api *operations.ConsoleAPI) {
|
||||
}
|
||||
return user_api.NewLoginDetailOK().WithPayload(loginDetails)
|
||||
})
|
||||
// post login
|
||||
// POST login using user credentials
|
||||
api.UserAPILoginHandler = user_api.LoginHandlerFunc(func(params user_api.LoginParams) middleware.Responder {
|
||||
loginResponse, err := getLoginResponse(params.Body)
|
||||
if err != nil {
|
||||
@@ -54,9 +54,10 @@ func registerLoginHandlers(api *operations.ConsoleAPI) {
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
|
||||
cookie := NewSessionCookieForConsole(loginResponse.SessionID)
|
||||
http.SetCookie(w, &cookie)
|
||||
user_api.NewLoginCreated().WithPayload(loginResponse).WriteResponse(w, p)
|
||||
user_api.NewLoginNoContent().WriteResponse(w, p)
|
||||
})
|
||||
})
|
||||
// POST login using external IDP
|
||||
api.UserAPILoginOauth2AuthHandler = user_api.LoginOauth2AuthHandlerFunc(func(params user_api.LoginOauth2AuthParams) middleware.Responder {
|
||||
loginResponse, err := getLoginOauth2AuthResponse(params.Body)
|
||||
if err != nil {
|
||||
@@ -66,19 +67,7 @@ func registerLoginHandlers(api *operations.ConsoleAPI) {
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
|
||||
cookie := NewSessionCookieForConsole(loginResponse.SessionID)
|
||||
http.SetCookie(w, &cookie)
|
||||
user_api.NewLoginOauth2AuthCreated().WithPayload(loginResponse).WriteResponse(w, p)
|
||||
})
|
||||
})
|
||||
api.UserAPILoginOperatorHandler = user_api.LoginOperatorHandlerFunc(func(params user_api.LoginOperatorParams) middleware.Responder {
|
||||
loginResponse, err := getLoginOperatorResponse(params.Body)
|
||||
if err != nil {
|
||||
return user_api.NewLoginOperatorDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
// Custom response writer to set the session cookies
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
|
||||
cookie := NewSessionCookieForConsole(loginResponse.SessionID)
|
||||
http.SetCookie(w, &cookie)
|
||||
user_api.NewLoginOperatorCreated().WithPayload(loginResponse).WriteResponse(w, p)
|
||||
user_api.NewLoginOauth2AuthNoContent().WriteResponse(w, p)
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -189,7 +178,7 @@ func getLoginOauth2AuthResponse(lr *models.LoginOauth2AuthRequest) (*models.Logi
|
||||
// Validate user against IDP
|
||||
userCredentials, err := verifyUserAgainstIDP(ctx, identityProvider, *lr.Code, *lr.State)
|
||||
if err != nil {
|
||||
return nil, prepareError(errInvalidCredentials, nil, err)
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// initialize admin client
|
||||
// login user against console and generate session token
|
||||
@@ -198,7 +187,7 @@ func getLoginOauth2AuthResponse(lr *models.LoginOauth2AuthRequest) (*models.Logi
|
||||
AccountAccessKey: "",
|
||||
})
|
||||
if err != nil {
|
||||
return nil, prepareError(errInvalidCredentials, nil, err)
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// serialize output
|
||||
loginResponse := &models.LoginResponse{
|
||||
@@ -208,21 +197,3 @@ func getLoginOauth2AuthResponse(lr *models.LoginOauth2AuthRequest) (*models.Logi
|
||||
}
|
||||
return nil, prepareError(ErrorGeneric)
|
||||
}
|
||||
|
||||
// getLoginOperatorResponse validate the provided service account token against k8s api
|
||||
func getLoginOperatorResponse(lmr *models.LoginOperatorRequest) (*models.LoginResponse, *models.Error) {
|
||||
creds, err := NewConsoleCredentials("", *lmr.Jwt, "")
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
consoleCreds := ConsoleCredentials{ConsoleCredentials: creds}
|
||||
token, err := login(consoleCreds)
|
||||
if err != nil {
|
||||
return nil, prepareError(errInvalidCredentials, nil, err)
|
||||
}
|
||||
// serialize output
|
||||
loginResponse := &models.LoginResponse{
|
||||
SessionID: *token,
|
||||
}
|
||||
return loginResponse, nil
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
xoauth2 "golang.org/x/oauth2"
|
||||
|
||||
"github.com/minio/madmin-go"
|
||||
|
||||
iampolicy "github.com/minio/pkg/iam/policy"
|
||||
@@ -78,12 +80,17 @@ func TestLogin(t *testing.T) {
|
||||
type IdentityProviderMock struct{}
|
||||
|
||||
var idpVerifyIdentityMock func(ctx context.Context, code, state string) (*credentials.Credentials, error)
|
||||
var idpVerifyIdentityForOperatorMock func(ctx context.Context, code, state string) (*xoauth2.Token, error)
|
||||
var idpGenerateLoginURLMock func() string
|
||||
|
||||
func (ac IdentityProviderMock) VerifyIdentity(ctx context.Context, code, state string) (*credentials.Credentials, error) {
|
||||
return idpVerifyIdentityMock(ctx, code, state)
|
||||
}
|
||||
|
||||
func (ac IdentityProviderMock) VerifyIdentityForOperator(ctx context.Context, code, state string) (*xoauth2.Token, error) {
|
||||
return idpVerifyIdentityForOperatorMock(ctx, code, state)
|
||||
}
|
||||
|
||||
func (ac IdentityProviderMock) GenerateLoginURL() string {
|
||||
return idpGenerateLoginURLMock()
|
||||
}
|
||||
|
||||
@@ -48,10 +48,8 @@ paths:
|
||||
schema:
|
||||
$ref: "#/definitions/loginRequest"
|
||||
responses:
|
||||
201:
|
||||
204:
|
||||
description: A successful login.
|
||||
schema:
|
||||
$ref: "#/definitions/loginResponse"
|
||||
default:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
@@ -60,29 +58,6 @@ paths:
|
||||
security: []
|
||||
tags:
|
||||
- UserAPI
|
||||
/login/operator:
|
||||
post:
|
||||
summary: Login to Operator Console.
|
||||
operationId: LoginOperator
|
||||
parameters:
|
||||
- name: body
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: "#/definitions/loginOperatorRequest"
|
||||
responses:
|
||||
201:
|
||||
description: A successful login.
|
||||
schema:
|
||||
$ref: "#/definitions/loginResponse"
|
||||
default:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
$ref: "#/definitions/error"
|
||||
security: []
|
||||
tags:
|
||||
- UserAPI
|
||||
|
||||
/login/oauth2/auth:
|
||||
post:
|
||||
summary: Identity Provider oauth2 callback endpoint.
|
||||
@@ -94,10 +69,8 @@ paths:
|
||||
schema:
|
||||
$ref: "#/definitions/loginOauth2AuthRequest"
|
||||
responses:
|
||||
201:
|
||||
204:
|
||||
description: A successful login.
|
||||
schema:
|
||||
$ref: "#/definitions/loginResponse"
|
||||
default:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
@@ -147,10 +120,8 @@ paths:
|
||||
schema:
|
||||
$ref: "#/definitions/accountChangePasswordRequest"
|
||||
responses:
|
||||
201:
|
||||
204:
|
||||
description: A successful login.
|
||||
schema:
|
||||
$ref: "#/definitions/loginResponse"
|
||||
default:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
@@ -3045,13 +3016,6 @@ definitions:
|
||||
type: string
|
||||
code:
|
||||
type: string
|
||||
loginOperatorRequest:
|
||||
type: object
|
||||
required:
|
||||
- jwt
|
||||
properties:
|
||||
jwt:
|
||||
type: string
|
||||
loginRequest:
|
||||
type: object
|
||||
required:
|
||||
|
||||
@@ -38,28 +38,6 @@ paths:
|
||||
security: [ ]
|
||||
tags:
|
||||
- UserAPI
|
||||
post:
|
||||
summary: Login to Console
|
||||
operationId: Login
|
||||
parameters:
|
||||
- name: body
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: "#/definitions/loginRequest"
|
||||
responses:
|
||||
201:
|
||||
description: A successful login.
|
||||
schema:
|
||||
$ref: "#/definitions/loginResponse"
|
||||
default:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
$ref: "#/definitions/error"
|
||||
# Exclude this API from the authentication requirement
|
||||
security: [ ]
|
||||
tags:
|
||||
- UserAPI
|
||||
/login/operator:
|
||||
post:
|
||||
summary: Login to Operator Console.
|
||||
@@ -71,10 +49,8 @@ paths:
|
||||
schema:
|
||||
$ref: "#/definitions/loginOperatorRequest"
|
||||
responses:
|
||||
201:
|
||||
204:
|
||||
description: A successful login.
|
||||
schema:
|
||||
$ref: "#/definitions/loginResponse"
|
||||
default:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
@@ -94,10 +70,8 @@ paths:
|
||||
schema:
|
||||
$ref: "#/definitions/loginOauth2AuthRequest"
|
||||
responses:
|
||||
201:
|
||||
204:
|
||||
description: A successful login.
|
||||
schema:
|
||||
$ref: "#/definitions/loginResponse"
|
||||
default:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
@@ -984,11 +958,6 @@ definitions:
|
||||
type: string
|
||||
secretKey:
|
||||
type: string
|
||||
loginResponse:
|
||||
type: object
|
||||
properties:
|
||||
sessionId:
|
||||
type: string
|
||||
loginOauth2AuthRequest:
|
||||
type: object
|
||||
required:
|
||||
|
||||
Reference in New Issue
Block a user