Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support password grant #258

Merged
merged 1 commit into from
Apr 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
feat: support password grant
  • Loading branch information
yadzhang committed Apr 10, 2020
commit bdc7beeb9d7c76f87c0454bdd4cbc88aa6058aed
5 changes: 3 additions & 2 deletions cmd/tke-auth-api/app/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func CreateConfigFromOptions(serverName string, opts *options.Options) (*Config,
}
setupAuthorization(genericAPIServerConfig, aggregateAuthz)

dexConfig, err := setupDexConfig(opts.ETCD, authClient, opts.Auth.AssetsPath, opts.Auth.IDTokenTimeout, opts.Generic.ExternalHost, opts.Generic.ExternalPort)
dexConfig, err := setupDexConfig(opts.ETCD, authClient, opts.Auth.AssetsPath, opts.Auth.IDTokenTimeout, opts.Generic.ExternalHost, opts.Generic.ExternalPort, opts.Auth.PasswordGrantConnID)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -236,7 +236,7 @@ func setupAuthorization(genericAPIServerConfig *genericapiserver.Config, authori
genericAPIServerConfig.Authorization.Authorizer = authorizer
}

func setupDexConfig(etcdOpts *storageoptions.ETCDStorageOptions, authClient authinternalclient.AuthInterface, templatePath string, tokenTimeout time.Duration, host string, port int) (*dexserver.Config, error) {
func setupDexConfig(etcdOpts *storageoptions.ETCDStorageOptions, authClient authinternalclient.AuthInterface, templatePath string, tokenTimeout time.Duration, host string, port int, passwordConnID string) (*dexserver.Config, error) {
logger := dex.NewLogger(log.ZapLogger())
issuer := issuer(host, port)
namespace := etcdOpts.Prefix
Expand Down Expand Up @@ -272,6 +272,7 @@ func setupDexConfig(etcdOpts *storageoptions.ETCDStorageOptions, authClient auth
SkipApprovalScreen: true,

PrometheusRegistry: prometheus.NewRegistry(),
PasswordConnector: passwordConnID,
}

return &dexConfig, nil
Expand Down
11 changes: 11 additions & 0 deletions cmd/tke-auth-api/app/options/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const (
flagAuthInitClientID = "init-client-id"
flagAuthInitClientSecret = "init-client-secret"
flagAuthInitClientRedirectUris = "init-client-redirect-uris"
flagAuthPasswordGrantConnID = "password-grant-conn-id"
)

const (
Expand All @@ -51,6 +52,7 @@ const (
configAuthInitClientID = "auth.init_client_id"
configAuthInitClientSecret = "auth.init_client_secret"
configAuthInitClientRedirectUris = "auth.init_client_redirect_uris"
configAuthPasswordGrantConnID = "auth.password_grant_conn_id"
)

// AuthOptions contains configuration items related to auth attributes.
Expand All @@ -64,6 +66,7 @@ type AuthOptions struct {
InitClientID string
InitClientSecret string
InitClientRedirectUris []string
PasswordGrantConnID string
}

// NewAuthOptions creates a AuthOptions object with default parameters.
Expand Down Expand Up @@ -113,6 +116,10 @@ func (o *AuthOptions) AddFlags(fs *pflag.FlagSet) {
fs.StringSlice(flagAuthInitClientRedirectUris, o.InitClientRedirectUris,
"Default client redirect uris will be created when started.")
_ = viper.BindPFlag(configAuthInitClientRedirectUris, fs.Lookup(flagAuthInitClientRedirectUris))

fs.String(flagAuthPasswordGrantConnID, o.PasswordGrantConnID,
"Default connector that can be used for password grant.")
_ = viper.BindPFlag(configAuthPasswordGrantConnID, fs.Lookup(flagAuthPasswordGrantConnID))
}

// ApplyFlags parsing parameters from the command line or configuration file
Expand Down Expand Up @@ -147,5 +154,9 @@ func (o *AuthOptions) ApplyFlags() []error {
}
o.InitClientRedirectUris = viper.GetStringSlice(configAuthInitClientRedirectUris)

if len(o.PasswordGrantConnID) == 0 {
o.PasswordGrantConnID = o.InitTenantID
}

return errs
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ require (
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/coreos/prometheus-operator v0.34.0
github.com/deislabs/oras v0.8.0 // indirect
github.com/dexidp/dex v0.0.0-20200319150056-3693b74791f4
github.com/dexidp/dex v0.0.0-20200408064242-83d8853fd969
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/docker/distribution v2.7.1+incompatible
github.com/docker/go-metrics v0.0.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ github.com/dexidp/dex v0.0.0-20200303100508-d820fd45d80c h1:rwimutyvV0/97FXbBtkO
github.com/dexidp/dex v0.0.0-20200303100508-d820fd45d80c/go.mod h1:7ic4FXokPpBxUHngMrp5MZQv4j6ixPoqF+1zC6QRlhw=
github.com/dexidp/dex v0.0.0-20200319150056-3693b74791f4 h1:f5pMr7VGOyj3tkMV7ryl96KFWVGSns/mDezZCVVkmXk=
github.com/dexidp/dex v0.0.0-20200319150056-3693b74791f4/go.mod h1:7ic4FXokPpBxUHngMrp5MZQv4j6ixPoqF+1zC6QRlhw=
github.com/dexidp/dex v0.0.0-20200408064242-83d8853fd969 h1:drMoVJ6/vWbEq9Ldxps8T9hvSqo1Nab6+Rx0Xv7ei0E=
github.com/dexidp/dex v0.0.0-20200408064242-83d8853fd969/go.mod h1:7ic4FXokPpBxUHngMrp5MZQv4j6ixPoqF+1zC6QRlhw=
github.com/dexidp/dex v2.13.0+incompatible h1:EQPpzCi51omkwBe0KYpRGaV3rk6CVvjcqeMGCe3Q00w=
github.com/dexidp/dex v2.13.0+incompatible/go.mod h1:cRGkPWqKhDD1FMCICe2JbYDdVR2xGLa38F6iuH/jNAs=
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
Expand Down
36 changes: 36 additions & 0 deletions pkg/gateway/api/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ func registerTokenRoute(container *restful.Container, oauthConfig *oauth2.Config
ws := new(restful.WebService)
ws.Path(fmt.Sprintf("/apis/%s/%s/tokens", GroupName, Version))

ws.Route(ws.
POST("/").
Doc("generate token by username and password").
Operation("createPasswordToken").
Produces(restful.MIME_JSON).
Returns(http.StatusCreated, "Created", v1.Status{}).
Returns(http.StatusInternalServerError, "InternalError", v1.Status{}).
Returns(http.StatusUnauthorized, "Unauthorized", v1.Status{}).
To(handleTokenGenerateFunc(oauthConfig, oidcHTTPClient)))
ws.Route(ws.
GET("info").
Doc("obtain the user information corresponding to the token").
Expand Down Expand Up @@ -78,6 +87,33 @@ func registerTokenRoute(container *restful.Container, oauthConfig *oauth2.Config
container.Add(ws)
}

func handleTokenGenerateFunc(oauthConfig *oauth2.Config, httpClient *http.Client) func(*restful.Request, *restful.Response) {
return func(request *restful.Request, response *restful.Response) {
username, password, err := retrievePassword(request.Request)
if err != nil {
responsewriters.WriteRawJSON(http.StatusUnauthorized, errors.NewUnauthorized(err.Error()), response.ResponseWriter)
return
}

ctx := gooidc.ClientContext(context.Background(), httpClient)
t, err := oauthConfig.PasswordCredentialsToken(ctx, username, password)
if err != nil {
responsewriters.WriteRawJSON(http.StatusUnauthorized, errors.NewUnauthorized(err.Error()), response.ResponseWriter)
return
}

if err := token.ResponseToken(t, response.ResponseWriter); err != nil {
responsewriters.WriteRawJSON(http.StatusInternalServerError, errors.NewInternalError(err), response.ResponseWriter)
return
}

responsewriters.WriteRawJSON(http.StatusCreated, v1.Status{
Status: v1.StatusSuccess,
Code: http.StatusCreated,
}, response.ResponseWriter)
}
}

func handleTokenInfo(oidcAuthenticator *oidc.Authenticator) func(*restful.Request, *restful.Response) {
return func(request *restful.Request, response *restful.Response) {
t, err := token.RetrieveToken(request.Request)
Expand Down