Refactored and added client credentials flow

This commit is contained in:
David Allen 2024-02-29 20:14:53 -07:00
parent f912890a2d
commit f490eb4fc4
No known key found for this signature in database
GPG key ID: 1D2A29322FBB6FCB
9 changed files with 113 additions and 41 deletions

View file

@ -129,12 +129,17 @@ func (client *Client) FetchCSRFToken(flowUrl string) error {
func (client *Client) FetchTokenFromAuthenticationServer(code string, remoteUrl string, state string) ([]byte, error) {
data := url.Values{
"grant_type": {"authorization_code"},
"code": {code},
"client_id": {client.Id},
"client_secret": {client.Secret},
"state": {state},
"redirect_uri": {strings.Join(client.RedirectUris, ",")},
}
// add optional params if valid
if code != "" {
data["code"] = []string{code}
}
if state != "" {
data["state"] = []string{state}
}
res, err := http.PostForm(remoteUrl, data)
if err != nil {
return nil, fmt.Errorf("failed to get ID token: %s", err)
@ -151,9 +156,16 @@ func (client *Client) FetchTokenFromAuthorizationServer(remoteUrl string, jwt st
// hydra endpoint: /oauth/token
data := "grant_type=" + url.QueryEscape("urn:ietf:params:oauth:grant-type:jwt-bearer") +
"&client_id=" + client.Id +
"&client_secret=" + client.Secret +
"&scope=" + strings.Join(scope, "+") +
"&assertion=" + jwt
"&client_secret=" + client.Secret
// add optional params if valid
if jwt != "" {
data += "&assertion=" + jwt
}
if scope != nil || len(scope) > 0 {
data += "&scope=" + strings.Join(scope, "+")
}
fmt.Printf("encoded params: %v\n\n", data)
req, err := http.NewRequest("POST", remoteUrl, bytes.NewBuffer([]byte(data)))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

View file

@ -44,10 +44,15 @@ func NewConfig() Config {
ResponseType: "code",
Scope: []string{"openid", "profile", "email"},
ActionUrls: ActionUrls{
Identities: "",
AccessToken: "",
TrustedIssuers: "",
ServerConfig: "",
Identities: "",
AccessToken: "",
TrustedIssuers: "",
ServerConfig: "",
JwksUri: "",
Login: "",
LoginFlowId: "",
RegisterClient: "",
AuthorizeClient: "",
},
OpenBrowser: false,
DecodeIdToken: false,

View file

@ -1,6 +1,7 @@
package opaal
package flows
import (
opaal "davidallendj/opaal/internal"
"davidallendj/opaal/internal/oidc"
"encoding/json"
"errors"
@ -12,15 +13,7 @@ import (
"github.com/davidallendj/go-utils/util"
)
func Login(config *Config) error {
if config == nil {
return fmt.Errorf("config is not valid")
}
// initialize client that will be used throughout login flow
server := NewServerWithConfig(config)
client := NewClientWithConfig(config)
func AuthorizationCode(config *opaal.Config, server *opaal.Server, client *opaal.Client) error {
// initiate the login flow and get a flow ID and CSRF token
{
err := client.InitiateLoginFlow(config.ActionUrls.Login)
@ -49,7 +42,7 @@ func Login(config *Config) error {
}
// check if all appropriate parameters are set in config
if !HasRequiredParams(config) {
if !opaal.HasRequiredParams(config) {
return fmt.Errorf("client ID must be set")
}

View file

@ -0,0 +1,29 @@
package flows
import (
opaal "davidallendj/opaal/internal"
"fmt"
)
func ClientCredentials(config *opaal.Config, server *opaal.Server, client *opaal.Client) error {
// register a new OAuth 2 client with authorization srever
_, err := client.RegisterOAuthClient(config.ActionUrls.RegisterClient, nil)
if err != nil {
return fmt.Errorf("failed to register OAuth client: %v", err)
}
// authorize the client
_, err = client.AuthorizeClient(config.ActionUrls.AuthorizeClient)
if err != nil {
return fmt.Errorf("failed to authorize client: %v", err)
}
// request a token from the authorization server
res, err := client.FetchTokenFromAuthorizationServer(config.ActionUrls.AccessToken, "", nil)
if err != nil {
return fmt.Errorf("failed to fetch token from authorization server: %v", err)
}
fmt.Printf("token: %v\n", string(res))
return nil
}

28
internal/flows/login.go Normal file
View file

@ -0,0 +1,28 @@
package flows
import (
opaal "davidallendj/opaal/internal"
"fmt"
)
func Login(config *opaal.Config) error {
if config == nil {
return fmt.Errorf("config is not valid")
}
// initialize client that will be used throughout login flow
server := opaal.NewServerWithConfig(config)
client := opaal.NewClientWithConfig(config)
fmt.Printf("grant type: %v\n", config.GrantType)
if config.GrantType == "authorization_code" {
AuthorizationCode(config, server, client)
} else if config.GrantType == "client_credentials" {
ClientCredentials(config, server, client)
} else {
return fmt.Errorf("invalid grant type")
}
return nil
}

View file

@ -1,13 +1,15 @@
package opaal
type ActionUrls struct {
Identities string `yaml:"identities"`
TrustedIssuers string `yaml:"trusted-issuers"`
AccessToken string `yaml:"access-token"`
ServerConfig string `yaml:"server-config"`
JwksUri string `yaml:"jwks_uri"`
Login string `yaml:"login"`
LoginFlowId string `yaml:"login-flow-id"`
Identities string `yaml:"identities"`
TrustedIssuers string `yaml:"trusted-issuers"`
AccessToken string `yaml:"access-token"`
ServerConfig string `yaml:"server-config"`
JwksUri string `yaml:"jwks_uri"`
Login string `yaml:"login"`
LoginFlowId string `yaml:"login-flow-id"`
RegisterClient string `yaml:"register-client"`
AuthorizeClient string `yaml:"authorize-client"`
}
func HasRequiredParams(config *Config) bool {