Skip to content

Commit

Permalink
Foo
Browse files Browse the repository at this point in the history
  • Loading branch information
steve-r-west committed Nov 21, 2024
1 parent c9a3bd9 commit fa0b8c4
Show file tree
Hide file tree
Showing 9 changed files with 242 additions and 87 deletions.
92 changes: 67 additions & 25 deletions external/oidc/callback.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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{
Expand Down
81 changes: 81 additions & 0 deletions external/oidc/get_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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")
Expand Down
21 changes: 17 additions & 4 deletions external/oidc/site/callback.gohtml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{{ template "header" }}
{{ if ne .ErrorTitle "" }}
<h2>An error has occurred</h2>
<h2><span class="material-symbols-outlined error">error</span>An Error has Occurred</h2>
<h3>Error Type: {{ .ErrorTitle }}</h3>
<h3>Error Description: {{ .ErrorDescription }}</h3>
{{ else if eq .LoginType "AM" }}
<h2>Authentication Successful</h2>
<h2><span class="material-symbols-outlined success">check_circle</span> Authentication With Identity Provider Successful</h2>

To finish the authentication process, you must select an account. If you see no accounts make sure that <a href="https://elasticpath.dev/docs/api/accounts/get-v-2-settings-account-authentication"><code>auto_create_account_for_account_members</code></a> is enabled or manually create an account.
<code>
Expand All @@ -13,7 +13,7 @@
<br/>
</code>
<h4>Please Select An Account</h4>
<table style="border: 1px; margin-left: 40px;">
<table>
<tr>
<th>Account Name</th>
<th>Account ID</th>
Expand All @@ -27,8 +27,21 @@
<td><button onclick="window.location.href='/get_token?login_type=AM&token={{ index $.AccountTokenStructBase64 $i }}'">GO</button></td>
</tr>
{{ end }}</table>
{{ else if eq .LoginType "Customers" }}
<h2><span class="material-symbols-outlined success">check_circle</span> Authentication With Identity Provider Successful</h2>
To continue, press <b>GO</b> next to the Customer.
<table>
<tr>
<th>Customer ID</th>
<th>Action</th>
</tr>

{{ end }}
<tr>
<td>{{ .CustomerTokenResponse.Data.Id }}</td>
<td><button onclick="window.location.href='/get_token?login_type={{ .LoginType }}&token={{ .CustomerTokenStructBase64 }}'">GO</button></td>
</tr>
</table>
{{ end }}
<br/>
<br/>
<br/>
Expand Down
24 changes: 0 additions & 24 deletions external/oidc/site/done.gohtml

This file was deleted.

20 changes: 0 additions & 20 deletions external/oidc/site/error.gohtml

This file was deleted.

34 changes: 27 additions & 7 deletions external/oidc/site/get_token.gohtml
Original file line number Diff line number Diff line change
@@ -1,17 +1,37 @@
{{ template "header" }}
{{ if ne .ErrorTitle "" }}
<h2>An error has occurred</h2>
<h2><span class="material-symbols-outlined error">error</span>An Error has Occurred</h2>
<h3>Error Type: {{ .ErrorTitle }}</h3>
<h3>Error Description: {{ .ErrorDescription }}</h3>
{{ else if eq .LoginType "AM" }}

You have successfully logged in as:
<br/>
<br/>
<b>Account Name:</b> {{ .Name }}<br/>
<b>Account ID:</b> {{ .Id }}<br/>

<h2><span class="material-symbols-outlined success">check_circle</span> Authentication Complete</h2>
You are now authenticated as:
<table>
<tr>
<th>Account Name</th>
<th>Account ID</th>
</tr>
<tr>
<td>{{ .Name }}</td>
<td>{{ .Id }}</td>
</tr>
</table>
<h3>You may now close this window.</h3>
{{ else if eq .LoginType "Customers" }}

<h2><span class="material-symbols-outlined success">check_circle</span> Authentication Complete</h2>
You are now authenticated as:
<table>
<tr>
<th>Customer Name</th>
<th>Customer ID</th>
</tr>
<tr>
<td>{{ .Name }}</td>
<td>{{ .Id }}</td>
</tr>
</table>
<h3>You may now close this window.</h3>
{{ end }}
{{ template "footer" }}
3 changes: 2 additions & 1 deletion external/oidc/site/header.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Top Banner</title>
<link rel="stylesheet" href="static/style.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!--<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">-->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" />
</head>
<body>
<header class="top-banner">
Expand Down
Loading

0 comments on commit fa0b8c4

Please sign in to comment.