mirror of
https://github.com/davidallendj/opaal.git
synced 2025-12-20 03:27:02 -07:00
Made changes to get client credentials grant working
This commit is contained in:
parent
e67bc3e010
commit
5173701fa0
7 changed files with 135 additions and 64 deletions
|
|
@ -85,6 +85,7 @@ var loginCmd = &cobra.Command{
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// start the listener
|
||||||
err := opaal.Login(&config, &client, provider)
|
err := opaal.Login(&config, &client, provider)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("%v\n", err)
|
fmt.Printf("%v\n", err)
|
||||||
|
|
|
||||||
|
|
@ -8,33 +8,34 @@ import (
|
||||||
type ClientCredentialsFlowParams struct {
|
type ClientCredentialsFlowParams struct {
|
||||||
State string `yaml:"state"`
|
State string `yaml:"state"`
|
||||||
ResponseType string `yaml:"response-type"`
|
ResponseType string `yaml:"response-type"`
|
||||||
|
Client *oauth.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClientCredentialsFlowEndpoints struct {
|
type ClientCredentialsFlowEndpoints struct {
|
||||||
Create string
|
Clients string
|
||||||
Authorize string
|
Authorize string
|
||||||
Token string
|
Token string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientCredentialsFlow(eps ClientCredentialsFlowEndpoints, client *oauth.Client) error {
|
func NewClientCredentialsFlow(eps ClientCredentialsFlowEndpoints, params ClientCredentialsFlowParams) (string, error) {
|
||||||
// register a new OAuth 2 client with authorization srever
|
// register a new OAuth 2 client with authorization srever
|
||||||
_, err := client.CreateOAuthClient(eps.Create)
|
res, err := params.Client.CreateOAuthClient(eps.Clients, []oauth.GrantType{oauth.ClientCredentials})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to register OAuth client: %v", err)
|
return "", fmt.Errorf("failed to register OAuth client: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// authorize the client
|
// authorize the client
|
||||||
_, err = client.AuthorizeOAuthClient(eps.Authorize)
|
res, err = params.Client.AuthorizeOAuthClient(eps.Authorize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to authorize client: %v", err)
|
return "", fmt.Errorf("failed to authorize client: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// request a token from the authorization server
|
// request a token from the authorization server
|
||||||
res, err := client.PerformTokenGrant(eps.Token, "")
|
res, err = params.Client.PerformClientCredentialsTokenGrant(eps.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to fetch token from authorization server: %v", err)
|
return "", fmt.Errorf("failed to fetch token from authorization server: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("token: %v\n", string(res))
|
fmt.Printf("token: %v\n", string(res))
|
||||||
return nil
|
return string(res), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,14 @@ type JwtBearerFlowParams struct {
|
||||||
KeyPath string
|
KeyPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
type JwtBearerEndpoints struct {
|
type JwtBearerFlowEndpoints struct {
|
||||||
TrustedIssuers string
|
TrustedIssuers string
|
||||||
Token string
|
Token string
|
||||||
Clients string
|
Clients string
|
||||||
Register string
|
Register string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewJwtBearerFlow(eps JwtBearerEndpoints, params JwtBearerFlowParams) (string, error) {
|
func NewJwtBearerFlow(eps JwtBearerFlowEndpoints, params JwtBearerFlowParams) (string, error) {
|
||||||
// 1. verify that the JWT from the issuer is valid using all keys
|
// 1. verify that the JWT from the issuer is valid using all keys
|
||||||
var (
|
var (
|
||||||
idp = params.IdentityProvider
|
idp = params.IdentityProvider
|
||||||
|
|
@ -164,7 +164,7 @@ func NewJwtBearerFlow(eps JwtBearerEndpoints, params JwtBearerFlowParams) (strin
|
||||||
|
|
||||||
// 5. dynamically register new OAuth client and authorize it to make jwt_bearer request
|
// 5. dynamically register new OAuth client and authorize it to make jwt_bearer request
|
||||||
fmt.Printf("Registering new OAuth2 client with authorization server...\n")
|
fmt.Printf("Registering new OAuth2 client with authorization server...\n")
|
||||||
res, err = client.RegisterOAuthClient(eps.Register)
|
res, err = client.RegisterOAuthClient(eps.Register, []oauth.GrantType{oauth.JwtBearer})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to register client: %v", err)
|
return "", fmt.Errorf("failed to register client: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -189,7 +189,7 @@ func NewJwtBearerFlow(eps JwtBearerEndpoints, params JwtBearerFlowParams) (strin
|
||||||
return "", fmt.Errorf("failed to delete OAuth client: %v", err)
|
return "", fmt.Errorf("failed to delete OAuth client: %v", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("Attempting to re-create client...\n")
|
fmt.Printf("Attempting to re-create client...\n")
|
||||||
res, err := client.CreateOAuthClient(eps.Clients)
|
res, err := client.CreateOAuthClient(eps.Clients, []oauth.GrantType{oauth.JwtBearer})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to register client: %v", err)
|
return "", fmt.Errorf("failed to register client: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -210,7 +210,7 @@ func NewJwtBearerFlow(eps JwtBearerEndpoints, params JwtBearerFlowParams) (strin
|
||||||
if eps.Token != "" {
|
if eps.Token != "" {
|
||||||
fmt.Printf("Fetching access token from authorization server...\n")
|
fmt.Printf("Fetching access token from authorization server...\n")
|
||||||
fmt.Printf("jwt: %s\n", string(newJwt))
|
fmt.Printf("jwt: %s\n", string(newJwt))
|
||||||
res, err := client.PerformTokenGrant(eps.Token, string(newJwt))
|
res, err := client.PerformJwtBearerTokenGrant(eps.Token, string(newJwt))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to fetch access token: %v", err)
|
return "", fmt.Errorf("failed to fetch access token: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -237,7 +237,7 @@ func NewJwtBearerFlow(eps JwtBearerEndpoints, params JwtBearerFlowParams) (strin
|
||||||
return string(res), nil
|
return string(res), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ForwardToken(eps JwtBearerEndpoints, params JwtBearerFlowParams) error {
|
func ForwardToken(eps JwtBearerFlowEndpoints, params JwtBearerFlowParams) error {
|
||||||
var (
|
var (
|
||||||
client = params.Client
|
client = params.Client
|
||||||
idToken = params.IdToken
|
idToken = params.IdToken
|
||||||
|
|
@ -279,7 +279,7 @@ func ForwardToken(eps JwtBearerEndpoints, params JwtBearerFlowParams) error {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Printf("Registering new OAuth2 client with authorization server...\n")
|
fmt.Printf("Registering new OAuth2 client with authorization server...\n")
|
||||||
}
|
}
|
||||||
res, err := client.RegisterOAuthClient(eps.Register)
|
res, err := client.RegisterOAuthClient(eps.Register, []oauth.GrantType{oauth.JwtBearer})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to register client: %v", err)
|
return fmt.Errorf("failed to register client: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -306,7 +306,7 @@ func ForwardToken(eps JwtBearerEndpoints, params JwtBearerFlowParams) error {
|
||||||
return fmt.Errorf("failed to delete OAuth client: %v", err)
|
return fmt.Errorf("failed to delete OAuth client: %v", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("Attempting to re-create client...\n")
|
fmt.Printf("Attempting to re-create client...\n")
|
||||||
res, err := client.CreateOAuthClient(eps.Clients)
|
res, err := client.CreateOAuthClient(eps.Clients, []oauth.GrantType{oauth.JwtBearer})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to register client: %v", err)
|
return fmt.Errorf("failed to register client: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -327,7 +327,7 @@ func ForwardToken(eps JwtBearerEndpoints, params JwtBearerFlowParams) error {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Printf("Fetching access token from authorization server...\n")
|
fmt.Printf("Fetching access token from authorization server...\n")
|
||||||
}
|
}
|
||||||
res, err := client.PerformTokenGrant(eps.Token, idToken)
|
res, err := client.PerformJwtBearerTokenGrant(eps.Token, idToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to fetch access token: %v", err)
|
return fmt.Errorf("failed to fetch access token: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,15 @@ import (
|
||||||
|
|
||||||
func Login(config *Config, client *oauth.Client, provider *oidc.IdentityProvider) error {
|
func Login(config *Config, client *oauth.Client, provider *oidc.IdentityProvider) error {
|
||||||
if config == nil {
|
if config == nil {
|
||||||
return fmt.Errorf("config is not valid")
|
return fmt.Errorf("invalid config")
|
||||||
|
}
|
||||||
|
|
||||||
|
if client == nil {
|
||||||
|
return fmt.Errorf("invalid client")
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider == nil {
|
||||||
|
return fmt.Errorf("invalid identity provider")
|
||||||
}
|
}
|
||||||
|
|
||||||
// make cache if it's not where expect
|
// make cache if it's not where expect
|
||||||
|
|
@ -38,12 +46,13 @@ func Login(config *Config, client *oauth.Client, provider *oidc.IdentityProvider
|
||||||
)
|
)
|
||||||
|
|
||||||
var button = MakeButton(authorizationUrl, "Login with "+client.Name)
|
var button = MakeButton(authorizationUrl, "Login with "+client.Name)
|
||||||
var jwtClient = oauth.NewClient()
|
var authzClient = oauth.NewClient()
|
||||||
jwtClient.Scope = config.Authorization.Token.Scope
|
authzClient.Scope = config.Authorization.Token.Scope
|
||||||
|
|
||||||
// authorize oauth client and listen for callback from provider
|
// authorize oauth client and listen for callback from provider
|
||||||
fmt.Printf("Waiting for authorization code redirect @%s/oidc/callback...\n", s.GetListenAddr())
|
fmt.Printf("Waiting for authorization code redirect @%s/oidc/callback...\n", s.GetListenAddr())
|
||||||
params := server.ServerParams{
|
params := server.ServerParams{
|
||||||
|
Verbose: config.Options.Verbose,
|
||||||
AuthProvider: &oidc.IdentityProvider{
|
AuthProvider: &oidc.IdentityProvider{
|
||||||
Issuer: config.Authorization.Endpoints.Issuer,
|
Issuer: config.Authorization.Endpoints.Issuer,
|
||||||
Endpoints: oidc.Endpoints{
|
Endpoints: oidc.Endpoints{
|
||||||
|
|
@ -51,14 +60,13 @@ func Login(config *Config, client *oauth.Client, provider *oidc.IdentityProvider
|
||||||
JwksUri: config.Authorization.Endpoints.JwksUri,
|
JwksUri: config.Authorization.Endpoints.JwksUri,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Verbose: config.Options.Verbose,
|
JwtBearerEndpoints: flows.JwtBearerFlowEndpoints{
|
||||||
JwtBearerEndpoints: flows.JwtBearerEndpoints{
|
|
||||||
Token: config.Authorization.Endpoints.Token,
|
Token: config.Authorization.Endpoints.Token,
|
||||||
TrustedIssuers: config.Authorization.Endpoints.TrustedIssuers,
|
TrustedIssuers: config.Authorization.Endpoints.TrustedIssuers,
|
||||||
Register: config.Authorization.Endpoints.Register,
|
Register: config.Authorization.Endpoints.Register,
|
||||||
},
|
},
|
||||||
JwtBearerParams: flows.JwtBearerFlowParams{
|
JwtBearerParams: flows.JwtBearerFlowParams{
|
||||||
Client: jwtClient,
|
Client: authzClient,
|
||||||
IdentityProvider: provider,
|
IdentityProvider: provider,
|
||||||
TrustedIssuer: &oauth.TrustedIssuer{
|
TrustedIssuer: &oauth.TrustedIssuer{
|
||||||
AllowAnySubject: false,
|
AllowAnySubject: false,
|
||||||
|
|
@ -70,8 +78,16 @@ func Login(config *Config, client *oauth.Client, provider *oidc.IdentityProvider
|
||||||
Verbose: config.Options.Verbose,
|
Verbose: config.Options.Verbose,
|
||||||
Refresh: config.Authorization.Token.Refresh,
|
Refresh: config.Authorization.Token.Refresh,
|
||||||
},
|
},
|
||||||
|
ClientCredentialsEndpoints: flows.ClientCredentialsFlowEndpoints{
|
||||||
|
Clients: config.Authorization.Endpoints.Clients,
|
||||||
|
Authorize: config.Authorization.Endpoints.Authorize,
|
||||||
|
Token: config.Authorization.Endpoints.Token,
|
||||||
|
},
|
||||||
|
ClientCredentialsParams: flows.ClientCredentialsFlowParams{
|
||||||
|
Client: authzClient,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
err = s.Login(button, provider, client, params)
|
err = s.Start(button, provider, client, params)
|
||||||
if errors.Is(err, http.ErrServerClosed) {
|
if errors.Is(err, http.ErrServerClosed) {
|
||||||
fmt.Printf("\n=========================================\nServer closed.\n=========================================\n\n")
|
fmt.Printf("\n=========================================\nServer closed.\n=========================================\n\n")
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
|
@ -79,7 +95,10 @@ func Login(config *Config, client *oauth.Client, provider *oidc.IdentityProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if config.Options.FlowType == "client_credentials" {
|
} else if config.Options.FlowType == "client_credentials" {
|
||||||
err := NewClientCredentialsFlowWithConfig(config, client)
|
params := flows.ClientCredentialsFlowParams{
|
||||||
|
Client: client,
|
||||||
|
}
|
||||||
|
_, err := NewClientCredentialsFlowWithConfig(config, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("failed to complete client credentials flow: %v", err)
|
fmt.Printf("failed to complete client credentials flow: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,13 +72,13 @@ func NewClientWithConfigById(config *Config, id string) *oauth.Client {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientCredentialsFlowWithConfig(config *Config, client *oauth.Client) error {
|
func NewClientCredentialsFlowWithConfig(config *Config, params flows.ClientCredentialsFlowParams) (string, error) {
|
||||||
eps := flows.ClientCredentialsFlowEndpoints{
|
eps := flows.ClientCredentialsFlowEndpoints{
|
||||||
Create: config.Authorization.Endpoints.Clients,
|
Clients: config.Authorization.Endpoints.Clients,
|
||||||
Authorize: config.Authorization.Endpoints.Authorize,
|
Authorize: config.Authorization.Endpoints.Authorize,
|
||||||
Token: config.Authorization.Endpoints.Token,
|
Token: config.Authorization.Endpoints.Token,
|
||||||
}
|
}
|
||||||
return flows.NewClientCredentialsFlow(eps, client)
|
return flows.NewClientCredentialsFlow(eps, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServerWithConfig(conf *Config) *server.Server {
|
func NewServerWithConfig(conf *Config) *server.Server {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,14 @@ import (
|
||||||
"golang.org/x/net/publicsuffix"
|
"golang.org/x/net/publicsuffix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type GrantType = string
|
||||||
|
|
||||||
|
const (
|
||||||
|
AuthorizationCode GrantType = "authorization_code"
|
||||||
|
ClientCredentials GrantType = "client_credentials"
|
||||||
|
JwtBearer GrantType = "urn:ietf:params:oauth:grant-type:jwt-bearer"
|
||||||
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
http.Client
|
http.Client
|
||||||
Id string `db:"id" yaml:"id"`
|
Id string `db:"id" yaml:"id"`
|
||||||
|
|
@ -87,21 +95,25 @@ func (client *Client) GetOAuthClient(clientUrl string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) CreateOAuthClient(registerUrl string) ([]byte, error) {
|
func (client *Client) CreateOAuthClient(registerUrl string, grantTypes []GrantType) ([]byte, error) {
|
||||||
// hydra endpoint: POST /clients
|
// hydra endpoint: POST /clients
|
||||||
|
if client == nil {
|
||||||
|
return nil, fmt.Errorf("invalid client")
|
||||||
|
}
|
||||||
audience := util.QuoteArrayStrings(client.Audience)
|
audience := util.QuoteArrayStrings(client.Audience)
|
||||||
|
grantTypes = util.QuoteArrayStrings(grantTypes)
|
||||||
body := httpx.Body(fmt.Sprintf(`{
|
body := httpx.Body(fmt.Sprintf(`{
|
||||||
"client_id": "%s",
|
"client_id": "%s",
|
||||||
"client_name": "%s",
|
"client_name": "%s",
|
||||||
"client_secret": "%s",
|
"client_secret": "%s",
|
||||||
"token_endpoint_auth_method": "client_secret_post",
|
"token_endpoint_auth_method": "client_secret_post",
|
||||||
"scope": "%s",
|
"scope": "%s",
|
||||||
"grant_types": ["urn:ietf:params:oauth:grant-type:jwt-bearer"],
|
"grant_types": [%s],
|
||||||
"response_types": ["token"],
|
"response_types": ["token"],
|
||||||
"redirect_uris": ["http://127.0.0.1:3333/callback"],
|
"redirect_uris": ["http://127.0.0.1:3333/callback"],
|
||||||
"state": 12345678910,
|
"state": 12345678910,
|
||||||
"audience": [%s]
|
"audience": [%s]
|
||||||
}`, client.Id, client.Id, client.Secret, strings.Join(client.Scope, " "), strings.Join(audience, ","),
|
}`, client.Id, client.Id, client.Secret, strings.Join(client.Scope, " "), strings.Join(grantTypes, ","), strings.Join(audience, ","),
|
||||||
))
|
))
|
||||||
headers := httpx.Headers{
|
headers := httpx.Headers{
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -131,22 +143,23 @@ func (client *Client) CreateOAuthClient(registerUrl string) ([]byte, error) {
|
||||||
return b, err
|
return b, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) RegisterOAuthClient(registerUrl string) ([]byte, error) {
|
func (client *Client) RegisterOAuthClient(registerUrl string, grantTypes []GrantType) ([]byte, error) {
|
||||||
// hydra endpoint: POST /oauth2/register
|
// hydra endpoint: POST /oauth2/register
|
||||||
if registerUrl == "" {
|
if registerUrl == "" {
|
||||||
return nil, fmt.Errorf("no URL provided")
|
return nil, fmt.Errorf("no URL provided")
|
||||||
}
|
}
|
||||||
audience := util.QuoteArrayStrings(client.Audience)
|
audience := util.QuoteArrayStrings(client.Audience)
|
||||||
|
grantTypes = util.QuoteArrayStrings(grantTypes)
|
||||||
body := httpx.Body(fmt.Sprintf(`{
|
body := httpx.Body(fmt.Sprintf(`{
|
||||||
"client_name": "opaal",
|
"client_name": "opaal",
|
||||||
"token_endpoint_auth_method": "client_secret_post",
|
"token_endpoint_auth_method": "client_secret_post",
|
||||||
"scope": "%s",
|
"scope": "%s",
|
||||||
"grant_types": ["urn:ietf:params:oauth:grant-type:jwt-bearer"],
|
"grant_types": [%s],
|
||||||
"response_types": ["token"],
|
"response_types": ["token"],
|
||||||
"redirect_uris": ["http://127.0.0.1:3333/callback"],
|
"redirect_uris": ["http://127.0.0.1:3333/callback"],
|
||||||
"state": 12345678910,
|
"state": 12345678910,
|
||||||
"audience": [%s]
|
"audience": [%s]
|
||||||
}`, strings.Join(client.Scope, " "), strings.Join(audience, ","),
|
}`, strings.Join(client.Scope, " "), strings.Join(grantTypes, ","), strings.Join(audience, ","),
|
||||||
))
|
))
|
||||||
headers := httpx.Headers{
|
headers := httpx.Headers{
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -196,7 +209,7 @@ func (client *Client) AuthorizeOAuthClient(authorizeUrl string) ([]byte, error)
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) PerformTokenGrant(clientUrl string, encodedJwt string) ([]byte, error) {
|
func (client *Client) PerformJwtBearerTokenGrant(clientUrl string, encodedJwt string) ([]byte, error) {
|
||||||
// hydra endpoint: /oauth/token
|
// hydra endpoint: /oauth/token
|
||||||
body := "grant_type=" + url.QueryEscape("urn:ietf:params:oauth:grant-type:jwt-bearer") +
|
body := "grant_type=" + url.QueryEscape("urn:ietf:params:oauth:grant-type:jwt-bearer") +
|
||||||
"&client_id=" + client.Id +
|
"&client_id=" + client.Id +
|
||||||
|
|
@ -220,8 +233,29 @@ func (client *Client) PerformTokenGrant(clientUrl string, encodedJwt string) ([]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set flow ID back to empty string to indicate a completed flow
|
return b, err
|
||||||
client.FlowId = ""
|
}
|
||||||
|
|
||||||
|
func (client *Client) PerformClientCredentialsTokenGrant(clientUrl string) ([]byte, error) {
|
||||||
|
// hydra endpoint: /oauth/token
|
||||||
|
body := "grant_type=" + url.QueryEscape("client_credentials") +
|
||||||
|
"&client_id=" + client.Id +
|
||||||
|
"&client_secret=" + client.Secret +
|
||||||
|
"&redirect_uri=" + url.QueryEscape("http://127.0.0.1:3333/callback")
|
||||||
|
// add optional params if valid
|
||||||
|
if client.Scope != nil || len(client.Scope) > 0 {
|
||||||
|
body += "&scope=" + strings.Join(client.Scope, "+")
|
||||||
|
}
|
||||||
|
headers := httpx.Headers{
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
"Authorization": "Bearer " + client.RegistrationAccessToken,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, b, err := httpx.MakeHttpRequest(clientUrl, http.MethodPost, []byte(body), headers)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to make HTTP request: %v", err)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return b, err
|
return b, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,9 @@ type Server struct {
|
||||||
type ServerParams struct {
|
type ServerParams struct {
|
||||||
AuthProvider *oidc.IdentityProvider
|
AuthProvider *oidc.IdentityProvider
|
||||||
Verbose bool
|
Verbose bool
|
||||||
JwtBearerEndpoints flows.JwtBearerEndpoints
|
ClientCredentialsEndpoints flows.ClientCredentialsFlowEndpoints
|
||||||
|
ClientCredentialsParams flows.ClientCredentialsFlowParams
|
||||||
|
JwtBearerEndpoints flows.JwtBearerFlowEndpoints
|
||||||
JwtBearerParams flows.JwtBearerFlowParams
|
JwtBearerParams flows.JwtBearerFlowParams
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,7 +40,7 @@ func (s *Server) GetListenAddr() string {
|
||||||
return fmt.Sprintf("%s:%d", s.Host, s.Port)
|
return fmt.Sprintf("%s:%d", s.Host, s.Port)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Login(buttons string, provider *oidc.IdentityProvider, client *oauth.Client, params ServerParams) error {
|
func (s *Server) Start(buttons string, provider *oidc.IdentityProvider, client *oauth.Client, params ServerParams) error {
|
||||||
var target = ""
|
var target = ""
|
||||||
|
|
||||||
// check if callback is set
|
// check if callback is set
|
||||||
|
|
@ -114,14 +116,10 @@ func (s *Server) Login(buttons string, provider *oidc.IdentityProvider, client *
|
||||||
w.Write(jwks)
|
w.Write(jwks)
|
||||||
|
|
||||||
})
|
})
|
||||||
r.HandleFunc("/refresh", func(w http.ResponseWriter, r *http.Request) {
|
r.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) {
|
||||||
// use refresh token provided to do a refresh token grant
|
// use refresh token provided to do a refresh token grant
|
||||||
refreshToken := r.URL.Query().Get("refresh-token")
|
refreshToken := r.URL.Query().Get("refresh-token")
|
||||||
if refreshToken == "" {
|
if refreshToken != "" {
|
||||||
fmt.Printf("no refresh token provided")
|
|
||||||
http.Redirect(w, r, "/error", http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err := params.JwtBearerParams.Client.PerformRefreshTokenGrant(provider.Endpoints.Token, refreshToken)
|
_, err := params.JwtBearerParams.Client.PerformRefreshTokenGrant(provider.Endpoints.Token, refreshToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("failed to perform refresh token grant: %v\n", err)
|
fmt.Printf("failed to perform refresh token grant: %v\n", err)
|
||||||
|
|
@ -138,6 +136,17 @@ func (s *Server) Login(buttons string, provider *oidc.IdentityProvider, client *
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("failed to make request")
|
fmt.Printf("failed to make request")
|
||||||
http.Redirect(w, r, "/error", http.StatusInternalServerError)
|
http.Redirect(w, r, "/error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// perform a client credentials grant and return a token
|
||||||
|
var err error
|
||||||
|
accessToken, err = flows.NewClientCredentialsFlow(params.ClientCredentialsEndpoints, params.ClientCredentialsParams)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("failed to perform client credentials flow: %v\n", err)
|
||||||
|
http.Redirect(w, r, "/error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
r.HandleFunc(s.Callback, func(w http.ResponseWriter, r *http.Request) {
|
r.HandleFunc(s.Callback, func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
@ -196,6 +205,13 @@ func (s *Server) Login(buttons string, provider *oidc.IdentityProvider, client *
|
||||||
if params.Verbose {
|
if params.Verbose {
|
||||||
fmt.Printf("Serving success page.\n")
|
fmt.Printf("Serving success page.\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return only the token with no web page if "no-browser" header is set
|
||||||
|
noBrowser := r.Header.Get("no-browser")
|
||||||
|
if noBrowser != "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
template, err := gonja.FromFile("pages/success.html")
|
template, err := gonja.FromFile("pages/success.html")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue