-
- Account Name: {{ .AccountName }}
- Account ID: {{ .AccountId }}
- - -
diff --git a/external/oidc/callback.go b/external/oidc/callback.go index 6831829..89b5760 100644 --- a/external/oidc/callback.go +++ b/external/oidc/callback.go @@ -12,11 +12,13 @@ import ( ) type CallbackPageInfo struct { - LoginType string - ErrorTitle string - ErrorDescription string - AccountTokenResponse *authentication.AccountManagementAuthenticationTokenResponse - AccountTokenStructBase64 []string + LoginType string + ErrorTitle string + ErrorDescription string + AccountTokenResponse *authentication.AccountManagementAuthenticationTokenResponse + CustomerTokenResponse *authentication.CustomerTokenResponse + AccountTokenStructBase64 []string + CustomerTokenStructBase64 string } func GetCallbackData(ctx context.Context, port uint16, r *http.Request) (*CallbackPageInfo, error) { @@ -45,42 +47,82 @@ func GetCallbackData(ctx context.Context, port uint16, r *http.Request) (*Callba return nil, fmt.Errorf("could not get verifier cookie: %w", err) } - result, err := rest.CreateInternal(context.Background(), &httpclient.HttpParameterOverrides{}, []string{"account-management-authentication-token", - "authentication_mechanism", "oidc", - "oauth_authorization_code", data["code"], - "oauth_redirect_uri", fmt.Sprintf("http://localhost:%d/callback", port), - "oauth_state", state.Value, - "oauth_code_verifier", verifier.Value, - }, false, "", true) + login_type, err := r.Cookie("login_type") if err != nil { - return nil, fmt.Errorf("could not get account tokens: %w", err) + return nil, fmt.Errorf("could not get login_type cookie: %w", err) + } + + if data["state"] != state.Value { + return &CallbackPageInfo{ + ErrorTitle: "State Mismatch", + ErrorDescription: "State mismatch between locally stored value and value from IdP", + LoginType: login_type.Value, + }, nil } cpi := CallbackPageInfo{ - LoginType: "AM", + LoginType: login_type.Value, } - err = gojson.Unmarshal([]byte(result), &cpi.AccountTokenResponse) + if login_type.Value == "AM" { + result, err := rest.CreateInternal(context.Background(), &httpclient.HttpParameterOverrides{}, []string{"account-management-authentication-token", + "authentication_mechanism", "oidc", + "oauth_authorization_code", data["code"], + "oauth_redirect_uri", fmt.Sprintf("http://localhost:%d/callback", port), + "oauth_code_verifier", verifier.Value, + }, false, "", true) - if err != nil { - return nil, fmt.Errorf("could not unmarshal response: %w", err) - } + if err != nil { + return nil, fmt.Errorf("could not get account tokens: %w", err) + } + + err = gojson.Unmarshal([]byte(result), &cpi.AccountTokenResponse) + + if err != nil { + return nil, fmt.Errorf("could not unmarshal response: %w", err) + } + + for _, v := range cpi.AccountTokenResponse.Data { - for _, v := range cpi.AccountTokenResponse.Data { + str, err := gojson.Marshal(v) - str, err := gojson.Marshal(v) + if err != nil { + return nil, fmt.Errorf("could not encode token: %w", err) + } + + cpi.AccountTokenStructBase64 = append(cpi.AccountTokenStructBase64, base64.URLEncoding.EncodeToString(str)) + } + + return &cpi, nil + } else if login_type.Value == "Customers" { + result, err := rest.CreateInternal(context.Background(), &httpclient.HttpParameterOverrides{}, []string{"customer-token", + "authentication_mechanism", "oidc", + "oauth_authorization_code", data["code"], + "oauth_redirect_uri", fmt.Sprintf("http://localhost:%d/callback", port), + "oauth_code_verifier", verifier.Value, + }, false, "", true) if err != nil { - return nil, fmt.Errorf("could not encode token: %w", err) + return nil, fmt.Errorf("could not get customer tokens: %w", err) } - base64.URLEncoding.EncodeToString(str) + err = gojson.Unmarshal([]byte(result), &cpi.CustomerTokenResponse) - cpi.AccountTokenStructBase64 = append(cpi.AccountTokenStructBase64, base64.URLEncoding.EncodeToString(str)) - } + str, err := gojson.Marshal(cpi.CustomerTokenResponse.Data) - return &cpi, nil + if err != nil { + return nil, fmt.Errorf("could not encode token: %w", err) + } + + cpi.CustomerTokenStructBase64 = base64.URLEncoding.EncodeToString(str) + return &cpi, nil + } else { + return &CallbackPageInfo{ + ErrorTitle: "Unknown Login Type", + ErrorDescription: fmt.Sprintf("Unsupported login type used: %v", login_type.Value), + }, nil + } } else if data["error"] == "" { return &CallbackPageInfo{ diff --git a/external/oidc/get_token.go b/external/oidc/get_token.go index db32650..f91a085 100644 --- a/external/oidc/get_token.go +++ b/external/oidc/get_token.go @@ -6,6 +6,9 @@ import ( gojson "encoding/json" "fmt" "github.com/elasticpath/epcc-cli/external/authentication" + "github.com/elasticpath/epcc-cli/external/httpclient" + "github.com/elasticpath/epcc-cli/external/json" + "github.com/elasticpath/epcc-cli/external/rest" log "github.com/sirupsen/logrus" "net/http" "os" @@ -68,6 +71,84 @@ func GetTokenData(ctx context.Context, port uint16, r *http.Request) (*TokenPage Id: amToken.AccountId, }, nil + } else if data["login_type"] == "Customers" { + token := data["token"] + custToken, err := base64.URLEncoding.DecodeString(token) + + if err != nil { + return nil, fmt.Errorf("could not get decode am token: %w", err) + } + + custTokenStruct := authentication.CustomerTokenStruct{} + + err = gojson.Unmarshal(custToken, &custTokenStruct) + + if err != nil { + return nil, fmt.Errorf("could not get unmarshal am token: %w", err) + } + + ctr := authentication.CustomerTokenResponse{ + Data: custTokenStruct, + AdditionalInfo: authentication.CustomerTokenEpccCliAdditionalInfo{}, + } + + authentication.SaveCustomerToken(ctr) + + apiToken := authentication.GetApiToken() + + if apiToken != nil { + if apiToken.Identifier == "client_credentials" { + log.Warnf("You are currently logged in with client_credentials, please switch to implicit with `epcc login implicit` to use the customer token correctly. Mixing client_credentials and the customer token can lead to unintended results.") + } + } + + if authentication.IsAccountManagementAuthenticationTokenSet() { + log.Warnf("Logging out of Account Management") + authentication.ClearAccountManagementAuthenticationToken() + } + + result, err := rest.GetInternal(context.Background(), &httpclient.HttpParameterOverrides{}, []string{"customer", custTokenStruct.CustomerId}, false) + + customerName := "Unknown" + customerEmail := "Unkwown" + + if err == nil { + customerName, err = json.RunJQOnStringAndGetString(".data.name", result) + + if err != nil { + log.Warnf("Could not get customer name from response %s, %v", result, err) + } + + customerEmail, err = json.RunJQOnStringAndGetString(".data.email", result) + + if err != nil { + log.Warnf("Could not get customer email from response %s, %v", result, err) + } + + ctr := authentication.CustomerTokenResponse{ + Data: custTokenStruct, + AdditionalInfo: authentication.CustomerTokenEpccCliAdditionalInfo{ + CustomerName: customerName, + CustomerEmail: customerEmail, + }, + } + + log.Infof("Saving customer token with %s,%s, %v", customerName, customerEmail, result) + authentication.SaveCustomerToken(ctr) + } + + go func() { + time.Sleep(2 * time.Second) + log.Infof("Authentication complete, shutting down") + os.Exit(0) + }() + + return &TokenPageInfo{ + LoginType: "Customers", + Name: customerName, + Id: custTokenStruct.CustomerId, + }, nil + } return nil, fmt.Errorf("invalid login type") diff --git a/external/oidc/site/callback.gohtml b/external/oidc/site/callback.gohtml index aaea694..a698642 100644 --- a/external/oidc/site/callback.gohtml +++ b/external/oidc/site/callback.gohtml @@ -1,10 +1,10 @@ {{ template "header" }} {{ if ne .ErrorTitle "" }} -
auto_create_account_for_account_members
is enabled or manually create an account.
@@ -13,7 +13,7 @@
Account Name | Account ID | @@ -27,8 +27,21 @@
---|
Customer ID | +Action | +
---|---|
{{ .CustomerTokenResponse.Data.Id }} | ++ |
Account Name | +Account ID | +
---|---|
{{ .Name }} | +{{ .Id }} | +
Customer Name | +Customer ID | +
---|---|
{{ .Name }} | +{{ .Id }} | +
{{ $.RedirectUriUnencoded }}
to the Buyer Organization allowed redirect URIs.
+
+
+
+
+ epcc get customer-authentication-settings
+ epcc get authentication-realm related_authentication-realm_for_customer-authentication-settings_last_read=entity
+
+
+ After inspecting the list of redirect_uris, you can add a new one with the following syntax:
+
+
+
+ epcc update authentication-realm related_authentication-realm_for_customer-authentication-settings_last_read=entity redirect_uris[0] {{ $.RedirectUriUnencoded }}
+
+
+
+
+
+ epcc create oidc-profile related_authentication-realm_for_customer-authentication-settings_last_read=entity=entity name "EPCC CLI Test OIDC Profile" client_id my_client_id client_secret my_client_secret discovery_url my_discovery_url
+
+
+
+