mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 18:48:08 +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" | ||||
| 	"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) | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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
									
								
							
							
						
						
									
										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. | ||||
| - `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 | ||||
|  | ||||
|   | ||||
| @@ -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/). | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Hamid Ghaf
					Hamid Ghaf