Files
threshold/api/authmethods/authenticate.go
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

123 lines
3.3 KiB
Go
Raw Normal View History

// Copyright IBM Corp. 2020, 2026
2022-10-25 18:29:38 -05:00
// SPDX-License-Identifier: MPL-2.0
2023-02-02 17:15:17 -08:00
2020-08-07 12:55:02 -04:00
package authmethods
import (
"context"
2021-04-08 20:54:32 -04:00
"encoding/json"
2023-10-18 14:48:44 -07:00
"errors"
"fmt"
2021-04-08 20:54:32 -04:00
"github.com/hashicorp/boundary/api"
2023-10-18 14:48:44 -07:00
"github.com/hashicorp/boundary/api/authtokens"
)
2021-04-08 20:54:32 -04:00
type AuthenticateResult struct {
2022-10-25 18:29:38 -05:00
Command string `json:"-"`
Attributes map[string]any `json:"-"`
2021-04-08 20:54:32 -04:00
attributesRaw json.RawMessage
response *api.Response
}
func (a *AuthenticateResult) MarshalJSON() ([]byte, error) {
// Note that a will not be nil per contract of the interface. Using a map
// here causes Go to sort the resulting JSON, which makes tests easier and
// output more predictable.
2022-10-25 18:29:38 -05:00
out := make(map[string]any)
2021-04-08 20:54:32 -04:00
if a.Command != "" {
out["command"] = a.Command
}
if a.Attributes != nil {
out["attributes"] = a.Attributes
}
return json.Marshal(out)
}
func (a *AuthenticateResult) UnmarshalJSON(inBytes []byte) error {
type in struct {
Command string `json:"command"`
Attributes json.RawMessage `json:"attributes"`
}
i := new(in)
if err := json.Unmarshal(inBytes, i); err != nil {
return err
}
a.Command = i.Command
a.attributesRaw = i.Attributes
2022-10-25 18:29:38 -05:00
a.Attributes = make(map[string]any)
2021-04-08 20:54:32 -04:00
if err := json.Unmarshal(i.Attributes, &a.Attributes); err != nil {
return err
}
return nil
}
2023-10-18 14:48:44 -07:00
func (a AuthenticateResult) GetRawAttributes() json.RawMessage {
return a.attributesRaw
2021-04-08 20:54:32 -04:00
}
2023-10-18 14:48:44 -07:00
func (a AuthenticateResult) GetResponse() *api.Response {
return a.response
2021-04-08 20:54:32 -04:00
}
2023-10-18 14:48:44 -07:00
// GetAuthToken converts this AuthenticateResult into an AuthToken struct
func (a AuthenticateResult) GetAuthToken() (*authtokens.AuthToken, error) {
if a.attributesRaw == nil {
return nil, errors.New("AuthenticateResult does not have a populated raw attributes field")
}
token := new(authtokens.AuthToken)
if err := json.Unmarshal(a.GetRawAttributes(), token); err != nil {
return nil, err
}
return token, nil
}
// Authenticate is a generic authenticate API call that returns a generic
// result. See the documentation for the attributes required for any given auth
// method.
//
// Only some auth methods support multiple commands. If the documentation does
// not specify what command to use when and with which attriubutes, use
// "login".
2022-10-25 18:29:38 -05:00
func (c *Client) Authenticate(ctx context.Context, authMethodId, command string, attributes map[string]any, opt ...Option) (*AuthenticateResult, error) {
2020-08-07 12:55:02 -04:00
if c.client == nil {
2020-09-24 14:34:58 -07:00
return nil, fmt.Errorf("nil client in Authenticate request")
}
2021-04-08 20:54:32 -04:00
if authMethodId == "" {
return nil, fmt.Errorf("empty auth method passed into Authenticate request")
}
if command == "" {
return nil, fmt.Errorf("empty command passed into Authenticate request")
}
2020-07-22 00:14:28 -04:00
2020-08-07 12:55:02 -04:00
_, apiOpts := getOpts(opt...)
2022-10-25 18:29:38 -05:00
reqBody := map[string]any{
2021-04-08 20:54:32 -04:00
"command": command,
}
if attributes != nil {
reqBody["attributes"] = attributes
}
2020-08-07 12:55:02 -04:00
req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("auth-methods/%s:authenticate", authMethodId), reqBody, apiOpts...)
if err != nil {
2020-09-24 14:34:58 -07:00
return nil, fmt.Errorf("error creating Authenticate request: %w", err)
}
2020-08-07 12:55:02 -04:00
resp, err := c.client.Do(req)
if err != nil {
2020-09-24 14:34:58 -07:00
return nil, fmt.Errorf("error performing client request during Authenticate call: %w", err)
}
2021-04-08 20:54:32 -04:00
target := new(AuthenticateResult)
apiErr, err := resp.Decode(target)
if err != nil {
2020-09-24 14:34:58 -07:00
return nil, fmt.Errorf("error decoding Authenticate response: %w", err)
}
if apiErr != nil {
return nil, apiErr
}
2021-04-08 20:54:32 -04:00
target.response = resp
2020-09-24 14:34:58 -07:00
return target, nil
}