Expose auth settings through REST API
This commit is contained in:
parent
f44648a3ea
commit
60f35bef47
@ -5,6 +5,13 @@
|
||||
"entrypoint": "auth",
|
||||
"authentication": [],
|
||||
"apis": [
|
||||
{
|
||||
"name": "settings",
|
||||
"method": "GET",
|
||||
"title": "Returns auth settings",
|
||||
"path": "/",
|
||||
"parameters": {}
|
||||
},
|
||||
{
|
||||
"name": "check",
|
||||
"method": "GET",
|
||||
|
||||
@ -7,6 +7,13 @@
|
||||
"Authentication": [],
|
||||
"Path": "/auth",
|
||||
"APIs": [
|
||||
{
|
||||
"Name": "settings",
|
||||
"Method": "GET",
|
||||
"Title": "Returns auth settings",
|
||||
"Path": "/",
|
||||
"Parameters": {}
|
||||
},
|
||||
{
|
||||
"Name": "check",
|
||||
"Method": "GET",
|
||||
|
||||
@ -93,9 +93,23 @@
|
||||
|
||||
| Method | Endpoint | Purpose |
|
||||
| ------ | -------- | ------- |
|
||||
| `GET` | `/auth/` | Returns auth settings |
|
||||
| `GET` | `/auth/check` | Check JWT token |
|
||||
| `GET` | `/auth/logout` | Logout |
|
||||
|
||||
## Returns auth settings
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/auth/` | HTTP/S | GET | |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
|
||||
## Check JWT token
|
||||
|
||||
#### Method
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/markbates/goth"
|
||||
)
|
||||
|
||||
type (
|
||||
authSettings struct {
|
||||
// Password reset path (<frontend password reset url> "?token=" + <token>)
|
||||
@ -53,3 +59,38 @@ func AuthSettings(kv authSettingsStore) authSettings {
|
||||
internalPasswordResetEnabled: kv.Bool("auth.internal.password-reset.enabled"),
|
||||
}
|
||||
}
|
||||
|
||||
func (s authSettings) Format() map[string]interface{} {
|
||||
type (
|
||||
externalProvider struct {
|
||||
Label string `json:"label"`
|
||||
Handle string `json:"handle"`
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
providers = []externalProvider{}
|
||||
)
|
||||
|
||||
for p := range goth.GetProviders() {
|
||||
label := p
|
||||
if strings.Index(p, "openid-connect.") == 0 {
|
||||
label = strings.SplitN(p, ".", 2)[1]
|
||||
}
|
||||
|
||||
providers = append(providers, externalProvider{
|
||||
Label: label,
|
||||
Handle: p,
|
||||
})
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"internalEnabled": s.internalEnabled,
|
||||
"internalPasswordResetEnabled": s.internalPasswordResetEnabled,
|
||||
"internalSignUpEmailConfirmationRequired": s.internalSignUpEmailConfirmationRequired,
|
||||
"internalSignUpEnabled": s.internalSignUpEnabled,
|
||||
|
||||
"externalEnabled": s.externalEnabled,
|
||||
"externalProviders": providers,
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,17 +19,23 @@ var _ = errors.Wrap
|
||||
|
||||
type (
|
||||
Auth struct {
|
||||
jwt auth.TokenEncoder
|
||||
jwt auth.TokenEncoder
|
||||
authSettings authServiceSettingsProvider
|
||||
}
|
||||
|
||||
authServiceSettingsProvider interface {
|
||||
Format() map[string]interface{}
|
||||
}
|
||||
|
||||
checkResponse struct {
|
||||
JWT string `json:"jwt"`
|
||||
User *outgoing.User `json:"user"`
|
||||
}
|
||||
)
|
||||
|
||||
func (Auth) New() *Auth {
|
||||
return &Auth{}
|
||||
return &Auth{
|
||||
authSettings: service.DefaultAuthSettings,
|
||||
}
|
||||
}
|
||||
|
||||
func (ctrl *Auth) Check(ctx context.Context, r *request.AuthCheck) (interface{}, error) {
|
||||
@ -40,6 +46,10 @@ func (ctrl *Auth) Logout(ctx context.Context, r *request.AuthLogout) (interface{
|
||||
return nil, errors.New("Not implemented: Auth.logout")
|
||||
}
|
||||
|
||||
func (ctrl *Auth) Settings(ctx context.Context, r *request.AuthSettings) (interface{}, error) {
|
||||
return ctrl.authSettings.Format(), nil
|
||||
}
|
||||
|
||||
// Handlers() func ignores "std" crust controllers
|
||||
//
|
||||
// Crush handlers are too abstract for our auth needs so we need (direct access to htt.ResponseWriter)
|
||||
@ -74,5 +84,9 @@ func (ctrl *Auth) Handlers(jwtEncoder auth.TokenEncoder) *handlers.Auth {
|
||||
jwtEncoder.SetCookie(w, r, nil)
|
||||
}
|
||||
|
||||
h.Settings = func(w http.ResponseWriter, r *http.Request) {
|
||||
resputil.JSON(w, ctrl.authSvc.FormatSettings())
|
||||
}
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
@ -28,18 +28,27 @@ import (
|
||||
|
||||
// Internal API interface
|
||||
type AuthAPI interface {
|
||||
Settings(context.Context, *request.AuthSettings) (interface{}, error)
|
||||
Check(context.Context, *request.AuthCheck) (interface{}, error)
|
||||
Logout(context.Context, *request.AuthLogout) (interface{}, error)
|
||||
}
|
||||
|
||||
// HTTP API interface
|
||||
type Auth struct {
|
||||
Check func(http.ResponseWriter, *http.Request)
|
||||
Logout func(http.ResponseWriter, *http.Request)
|
||||
Settings func(http.ResponseWriter, *http.Request)
|
||||
Check func(http.ResponseWriter, *http.Request)
|
||||
Logout func(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
||||
func NewAuth(ah AuthAPI) *Auth {
|
||||
return &Auth{
|
||||
Settings: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewAuthSettings()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return ah.Settings(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Check: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewAuthCheck()
|
||||
@ -60,6 +69,7 @@ func NewAuth(ah AuthAPI) *Auth {
|
||||
func (ah *Auth) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.Handler) {
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(middlewares...)
|
||||
r.Get("/auth/", ah.Settings)
|
||||
r.Get("/auth/check", ah.Check)
|
||||
r.Get("/auth/logout", ah.Logout)
|
||||
})
|
||||
|
||||
@ -30,6 +30,46 @@ import (
|
||||
var _ = chi.URLParam
|
||||
var _ = multipart.FileHeader{}
|
||||
|
||||
// Auth settings request parameters
|
||||
type AuthSettings struct {
|
||||
}
|
||||
|
||||
func NewAuthSettings() *AuthSettings {
|
||||
return &AuthSettings{}
|
||||
}
|
||||
|
||||
func (auReq *AuthSettings) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(auReq)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := r.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := r.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewAuthSettings()
|
||||
|
||||
// Auth check request parameters
|
||||
type AuthCheck struct {
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user