mirror of
https://github.com/davidallendj/opaal.git
synced 2025-12-19 19:17:01 -07:00
Added refresh token flow
This commit is contained in:
parent
6938037a3c
commit
16ec8fc422
4 changed files with 56 additions and 2 deletions
|
|
@ -24,6 +24,7 @@ type Options struct {
|
|||
CachePath string `yaml:"cache"`
|
||||
CacheOnly bool `yaml:"cache-only"`
|
||||
TokenForwarding bool `yaml:"token-forwarding"`
|
||||
Refresh bool `yaml:"refresh"`
|
||||
Verbose bool `yaml:"verbose"`
|
||||
}
|
||||
|
||||
|
|
@ -72,6 +73,7 @@ func NewConfig() Config {
|
|||
FlowType: "authorization_code",
|
||||
CacheOnly: false,
|
||||
TokenForwarding: false,
|
||||
Refresh: true,
|
||||
Verbose: false,
|
||||
},
|
||||
Authentication: Authentication{
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ type JwtBearerFlowParams struct {
|
|||
IdentityProvider *oidc.IdentityProvider
|
||||
TrustedIssuer *oauth.TrustedIssuer
|
||||
Client *oauth.Client
|
||||
Refresh bool
|
||||
Verbose bool
|
||||
KeyPath string
|
||||
}
|
||||
|
|
@ -97,14 +98,19 @@ func NewJwtBearerFlow(eps JwtBearerEndpoints, params JwtBearerFlowParams) (strin
|
|||
}
|
||||
}
|
||||
|
||||
// add more required claims and validate
|
||||
publicJwk.Set("kid", uuid.New().String())
|
||||
publicJwk.Set("use", "sig")
|
||||
|
||||
if err := publicJwk.Validate(); err != nil {
|
||||
return "", fmt.Errorf("failed to validate public JWK: %v", err)
|
||||
}
|
||||
trustedIssuer.PublicKey = publicJwk
|
||||
|
||||
// add offline_access scope to enable refresh tokens
|
||||
if params.Refresh {
|
||||
trustedIssuer.Scope = append(trustedIssuer.Scope, "offline_access")
|
||||
}
|
||||
|
||||
// 3.b ...and then, add opaal's server host as a trusted issuer with JWK
|
||||
if verbose {
|
||||
fmt.Printf("Attempting to add issuer to authorization server...\n")
|
||||
|
|
@ -131,6 +137,13 @@ func NewJwtBearerFlow(eps JwtBearerEndpoints, params JwtBearerFlowParams) (strin
|
|||
payload["nbf"] = time.Now().Unix()
|
||||
payload["exp"] = time.Now().Add(time.Second * 3600).Unix()
|
||||
payload["sub"] = "opaal"
|
||||
|
||||
// include the offline_access scope if refresh tokens are enabled
|
||||
if params.Refresh {
|
||||
scope := payload["scp"].([]string)
|
||||
scope = append(scope, "offline_access")
|
||||
payload["scp"] = scope
|
||||
}
|
||||
payloadJson, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to marshal payload: %v", err)
|
||||
|
|
|
|||
|
|
@ -211,6 +211,10 @@ func (client *Client) PerformTokenGrant(clientUrl string, encodedJwt string) ([]
|
|||
}
|
||||
|
||||
_, b, err := httpx.MakeHttpRequest(clientUrl, http.MethodPost, []byte(body), headers)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to make HTTP request: %v", err)
|
||||
|
||||
}
|
||||
|
||||
// set flow ID back to empty string to indicate a completed flow
|
||||
client.FlowId = ""
|
||||
|
|
@ -218,6 +222,18 @@ func (client *Client) PerformTokenGrant(clientUrl string, encodedJwt string) ([]
|
|||
return b, err
|
||||
}
|
||||
|
||||
func (client *Client) PerformRefreshTokenGrant(url string, refreshToken string) ([]byte, error) {
|
||||
body := httpx.Body("grant_type=refresh_token" +
|
||||
"&refresh_token=" + refreshToken +
|
||||
"&scope" + strings.Join(client.Scope, "+"))
|
||||
headers := httpx.Headers{}
|
||||
_, b, err := httpx.MakeHttpRequest(url, http.MethodPost, body, headers)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to make HTTP request: %v", err)
|
||||
}
|
||||
return b, err
|
||||
}
|
||||
|
||||
func (client *Client) DeleteOAuthClient(clientUrl string) error {
|
||||
_, _, err := httpx.MakeHttpRequest(clientUrl+"/"+client.Id, http.MethodDelete, nil, nil)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -66,6 +66,29 @@ func (s *Server) Login(buttons string, provider *oidc.IdentityProvider, client *
|
|||
panic(err)
|
||||
}
|
||||
})
|
||||
r.HandleFunc("/key", func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
})
|
||||
r.HandleFunc("/refresh", func(w http.ResponseWriter, r *http.Request) {
|
||||
// use refresh token provided to do a refresh token grant
|
||||
refreshToken := r.URL.Query().Get("refresh-token")
|
||||
_, err := client.PerformRefreshTokenGrant(provider.Endpoints.Token, refreshToken)
|
||||
if err != nil {
|
||||
fmt.Printf("failed to perform refresh token grant: %v\n", err)
|
||||
http.Redirect(w, r, "/error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// return token to target if set or the sending client
|
||||
returnTarget := r.URL.Query().Get("target")
|
||||
if returnTarget != "" {
|
||||
|
||||
} else {
|
||||
host := r.URL.Host
|
||||
httpx.MakeHttpRequest(host, http.MethodPost, httpx.Body{}, httpx.Headers{})
|
||||
|
||||
}
|
||||
})
|
||||
r.HandleFunc(s.Callback, func(w http.ResponseWriter, r *http.Request) {
|
||||
// get the code from the OIDC provider
|
||||
if r != nil {
|
||||
|
|
@ -104,7 +127,7 @@ func (s *Server) Login(buttons string, provider *oidc.IdentityProvider, client *
|
|||
return
|
||||
}
|
||||
|
||||
// extract scopes from ID token and add to trusted issuer
|
||||
// TODO: extract scopes from ID token and add to trusted issuer
|
||||
|
||||
// complete JWT bearer flow to receive access token from authorization server
|
||||
// fmt.Printf("bearer: %v\n", string(bearerToken))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue