mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 11:08:10 +00:00
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:
@@ -6,6 +6,7 @@ import (
|
|||||||
"net/textproto"
|
"net/textproto"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-secure-stdlib/strutil"
|
||||||
"github.com/hashicorp/vault/helper/mfa"
|
"github.com/hashicorp/vault/helper/mfa"
|
||||||
"github.com/hashicorp/vault/sdk/framework"
|
"github.com/hashicorp/vault/sdk/framework"
|
||||||
"github.com/hashicorp/vault/sdk/helper/cidrutil"
|
"github.com/hashicorp/vault/sdk/helper/cidrutil"
|
||||||
@@ -63,7 +64,7 @@ type backend struct {
|
|||||||
*framework.Backend
|
*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)
|
cfg, err := b.Config(ctx, req.Storage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
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 {
|
for _, v := range result.Embedded.Factors {
|
||||||
v := v // create a new copy since we'll be taking the address later
|
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
|
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
|
// Okta push and totp, and Google totp are currently supported.
|
||||||
// login and is supported, that will be the preferred method.
|
// If a totp passcode is provided during login and is supported,
|
||||||
|
// that will be the preferred method.
|
||||||
switch {
|
switch {
|
||||||
case totpFactor != nil && totp != "":
|
case totpFactor != nil && totp != "":
|
||||||
selectedFactor = totpFactor
|
selectedFactor = totpFactor
|
||||||
case pushFactor != nil:
|
case pushFactor != nil && pushFactor.Provider == oktaProvider:
|
||||||
selectedFactor = pushFactor
|
selectedFactor = pushFactor
|
||||||
case totpFactor != nil && totp == "":
|
case totpFactor != nil && totp == "":
|
||||||
return nil, logical.ErrorResponse("'totp' passcode parameter is required to perform MFA"), nil, nil
|
return nil, logical.ErrorResponse("'totp' passcode parameter is required to perform MFA"), nil, nil
|
||||||
default:
|
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)
|
requestPath := fmt.Sprintf("authn/factors/%s/verify", selectedFactor.Id)
|
||||||
|
|||||||
@@ -38,11 +38,16 @@ func (h *CLIHandler) Auth(c *api.Client, m map[string]string) (*api.Secret, erro
|
|||||||
"password": password,
|
"password": password,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Okta totp code
|
// Okta or Google totp code
|
||||||
if totp, ok := m["totp"]; ok {
|
if totp, ok := m["totp"]; ok {
|
||||||
data["totp"] = totp
|
data["totp"] = totp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// provider is an optional parameter
|
||||||
|
if provider, ok := m["provider"]; ok {
|
||||||
|
data["provider"] = provider
|
||||||
|
}
|
||||||
|
|
||||||
// Legacy MFA support
|
// Legacy MFA support
|
||||||
mfa_method, ok := m["method"]
|
mfa_method, ok := m["method"]
|
||||||
if ok {
|
if ok {
|
||||||
|
|||||||
@@ -8,9 +8,15 @@ import (
|
|||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/hashicorp/vault/sdk/framework"
|
"github.com/hashicorp/vault/sdk/framework"
|
||||||
"github.com/hashicorp/vault/sdk/helper/policyutil"
|
"github.com/hashicorp/vault/sdk/helper/policyutil"
|
||||||
|
"github.com/hashicorp/vault/sdk/helper/strutil"
|
||||||
"github.com/hashicorp/vault/sdk/logical"
|
"github.com/hashicorp/vault/sdk/logical"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
googleProvider = "GOOGLE"
|
||||||
|
oktaProvider = "OKTA"
|
||||||
|
)
|
||||||
|
|
||||||
func pathLogin(b *backend) *framework.Path {
|
func pathLogin(b *backend) *framework.Path {
|
||||||
return &framework.Path{
|
return &framework.Path{
|
||||||
Pattern: `login/(?P<username>.+)`,
|
Pattern: `login/(?P<username>.+)`,
|
||||||
@@ -28,6 +34,10 @@ func pathLogin(b *backend) *framework.Path {
|
|||||||
Type: framework.TypeString,
|
Type: framework.TypeString,
|
||||||
Description: "TOTP passcode.",
|
Description: "TOTP passcode.",
|
||||||
},
|
},
|
||||||
|
"provider": {
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Description: "Preferred factor provider.",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
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) {
|
func (b *backend) pathLoginAliasLookahead(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
username := d.Get("username").(string)
|
username := d.Get("username").(string)
|
||||||
if username == "" {
|
if username == "" {
|
||||||
@@ -59,8 +73,12 @@ func (b *backend) pathLogin(ctx context.Context, req *logical.Request, d *framew
|
|||||||
username := d.Get("username").(string)
|
username := d.Get("username").(string)
|
||||||
password := d.Get("password").(string)
|
password := d.Get("password").(string)
|
||||||
totp := d.Get("totp").(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
|
// Handle an internal error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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.
|
// 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.
|
// 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()) {
|
if err != nil || (resp != nil && resp.IsError()) {
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|||||||
3
changelog/14985.txt
Normal file
3
changelog/14985.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
```release-note:improvement
|
||||||
|
auth/okta: Add support for Google provider TOTP type in the Okta auth method
|
||||||
|
```
|
||||||
@@ -352,6 +352,7 @@ Login with the username and password.
|
|||||||
- `username` `(string: <required>)` - Username for this user.
|
- `username` `(string: <required>)` - Username for this user.
|
||||||
- `password` `(string: <required>)` - Password for the authenticating user.
|
- `password` `(string: <required>)` - Password for the authenticating user.
|
||||||
- `totp` `(string: <optional>)` - Okta Verify TOTP passcode.
|
- `totp` `(string: <optional>)` - Okta Verify TOTP passcode.
|
||||||
|
- `provider` `(string: <optional>)` - MFA TOTP factor provider. `GOOGLE` and `OKTA` are currently supported.
|
||||||
|
|
||||||
### Sample Payload
|
### Sample Payload
|
||||||
|
|
||||||
|
|||||||
@@ -54,13 +54,20 @@ The response will contain a token at `auth.client_token`:
|
|||||||
|
|
||||||
### MFA
|
### 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:
|
passcode may be provided via the `totp` parameter:
|
||||||
|
|
||||||
```shell-session
|
```shell-session
|
||||||
$ vault login -method=okta username=my-username totp=123456
|
$ 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.
|
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/).
|
The auth method uses the Okta [Authentication API](https://developer.okta.com/docs/reference/api/authn/).
|
||||||
|
|||||||
Reference in New Issue
Block a user