supporting google authenticator with Okta auth (#14985)

* supporting google authenticator with Okta auth

* minor fix

* CL

* feedback

* Update changelog/14985.txt

Co-authored-by: Calvin Leung Huang <1883212+calvn@users.noreply.github.com>

* updating docs

Co-authored-by: Calvin Leung Huang <1883212+calvn@users.noreply.github.com>
This commit is contained in:
Hamid Ghaf 2022-04-14 08:37:04 -04:00 committed by GitHub
parent 18f9a7775c
commit 299d3f096e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 50 additions and 10 deletions

View File

@ -6,6 +6,7 @@ import (
"net/textproto"
"time"
"github.com/hashicorp/go-secure-stdlib/strutil"
"github.com/hashicorp/vault/helper/mfa"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/cidrutil"
@ -63,7 +64,7 @@ type backend struct {
*framework.Backend
}
func (b *backend) Login(ctx context.Context, req *logical.Request, username, password, totp string) ([]string, *logical.Response, []string, error) {
func (b *backend) Login(ctx context.Context, req *logical.Request, username, password, totp, preferredProvider string) ([]string, *logical.Response, []string, error) {
cfg, err := b.Config(ctx, req.Storage)
if err != nil {
return nil, nil, nil, err
@ -179,7 +180,11 @@ func (b *backend) Login(ctx context.Context, req *logical.Request, username, pas
for _, v := range result.Embedded.Factors {
v := v // create a new copy since we'll be taking the address later
if v.Provider != "OKTA" {
if preferredProvider != "" && preferredProvider != v.Provider {
continue
}
if !strutil.StrListContains(b.getSupportedProviders(), v.Provider) {
continue
}
@ -191,17 +196,18 @@ func (b *backend) Login(ctx context.Context, req *logical.Request, username, pas
}
}
// Okta push and totp are currently supported. If a totp passcode is provided during
// login and is supported, that will be the preferred method.
// Okta push and totp, and Google totp are currently supported.
// If a totp passcode is provided during login and is supported,
// that will be the preferred method.
switch {
case totpFactor != nil && totp != "":
selectedFactor = totpFactor
case pushFactor != nil:
case pushFactor != nil && pushFactor.Provider == oktaProvider:
selectedFactor = pushFactor
case totpFactor != nil && totp == "":
return nil, logical.ErrorResponse("'totp' passcode parameter is required to perform MFA"), nil, nil
default:
return nil, logical.ErrorResponse("Okta Verify Push or TOTP factor is required in order to perform MFA"), nil, nil
return nil, logical.ErrorResponse("Okta Verify Push or TOTP or Google TOTP factor is required in order to perform MFA"), nil, nil
}
requestPath := fmt.Sprintf("authn/factors/%s/verify", selectedFactor.Id)

View File

@ -38,11 +38,16 @@ func (h *CLIHandler) Auth(c *api.Client, m map[string]string) (*api.Secret, erro
"password": password,
}
// Okta totp code
// Okta or Google totp code
if totp, ok := m["totp"]; ok {
data["totp"] = totp
}
// provider is an optional parameter
if provider, ok := m["provider"]; ok {
data["provider"] = provider
}
// Legacy MFA support
mfa_method, ok := m["method"]
if ok {

View File

@ -8,9 +8,15 @@ import (
"github.com/go-errors/errors"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/policyutil"
"github.com/hashicorp/vault/sdk/helper/strutil"
"github.com/hashicorp/vault/sdk/logical"
)
const (
googleProvider = "GOOGLE"
oktaProvider = "OKTA"
)
func pathLogin(b *backend) *framework.Path {
return &framework.Path{
Pattern: `login/(?P<username>.+)`,
@ -28,6 +34,10 @@ func pathLogin(b *backend) *framework.Path {
Type: framework.TypeString,
Description: "TOTP passcode.",
},
"provider": {
Type: framework.TypeString,
Description: "Preferred factor provider.",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
@ -40,6 +50,10 @@ func pathLogin(b *backend) *framework.Path {
}
}
func (b *backend) getSupportedProviders() []string {
return []string{googleProvider, oktaProvider}
}
func (b *backend) pathLoginAliasLookahead(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
username := d.Get("username").(string)
if username == "" {
@ -59,8 +73,12 @@ func (b *backend) pathLogin(ctx context.Context, req *logical.Request, d *framew
username := d.Get("username").(string)
password := d.Get("password").(string)
totp := d.Get("totp").(string)
preferredProvider := strings.ToUpper(d.Get("provider").(string))
if preferredProvider != "" && !strutil.StrListContains(b.getSupportedProviders(), preferredProvider) {
return logical.ErrorResponse(fmt.Sprintf("provider %s is not among the supported ones %v", preferredProvider, b.getSupportedProviders())), nil
}
policies, resp, groupNames, err := b.Login(ctx, req, username, password, totp)
policies, resp, groupNames, err := b.Login(ctx, req, username, password, totp, preferredProvider)
// Handle an internal error
if err != nil {
return nil, err
@ -124,7 +142,7 @@ func (b *backend) pathLoginRenew(ctx context.Context, req *logical.Request, d *f
// No TOTP entry is possible on renew. If push MFA is enabled it will still be triggered, however.
// Sending "" as the totp will prompt the push action if it is configured.
loginPolicies, resp, groupNames, err := b.Login(ctx, req, username, password, "")
loginPolicies, resp, groupNames, err := b.Login(ctx, req, username, password, "", "")
if err != nil || (resp != nil && resp.IsError()) {
return resp, err
}

3
changelog/14985.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
auth/okta: Add support for Google provider TOTP type in the Okta auth method
```

View File

@ -352,6 +352,7 @@ Login with the username and password.
- `username` `(string: <required>)` - Username for this user.
- `password` `(string: <required>)` - Password for the authenticating user.
- `totp` `(string: <optional>)` - Okta Verify TOTP passcode.
- `provider` `(string: <optional>)` - MFA TOTP factor provider. `GOOGLE` and `OKTA` are currently supported.
### Sample Payload

View File

@ -54,13 +54,20 @@ The response will contain a token at `auth.client_token`:
### MFA
Okta Verify Push and TOTP MFA methods are supported during login. For TOTP, the current
Okta Verify Push and TOTP MFA methods, and Google TOTP are supported during login. For TOTP, the current
passcode may be provided via the `totp` parameter:
```shell-session
$ vault login -method=okta username=my-username totp=123456
```
If both Okta TOTP and Google TOTP are enabled in your Okta account, make sure to pass in
the `provider` name to which the `totp` code belong.
```shell-session
$ vault login -method=okta username=my-username totp=123456 provider=GOOGLE
```
If `totp` is not set and MFA Push is configured in Okta, a Push will be sent during login.
The auth method uses the Okta [Authentication API](https://developer.okta.com/docs/reference/api/authn/).