Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement RFC 8628 #3912

Open
wants to merge 37 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
c6e06cc
chore: install fosite from branch (remove)
nsklikas Sep 25, 2024
c5456e9
fix: set utc expires_at
nsklikas Sep 25, 2024
5d65b78
fix: add redirect_uri to test
nsklikas Sep 25, 2024
390d9fb
fix: add rfc8628 providers to registry
nsklikas Feb 9, 2024
79e63d8
fix: update database schema
nsklikas Feb 9, 2024
909999a
fix: update oauth persister logic
nsklikas Sep 24, 2024
82ef5e6
feat: add device authorization endpoint handler
nsklikas Feb 9, 2024
76696dd
refactor: move logic to updateSessionWithRequest method
nsklikas Feb 28, 2024
122da39
fix: rename device auth endpoint handler
nsklikas Feb 28, 2024
66bacf8
feat: add device user verification handler
nsklikas Feb 28, 2024
04c25d8
fix: implement device user verification logic
nsklikas Feb 28, 2024
6b7810a
feat: update flow
nsklikas Mar 1, 2024
1a40e99
fix: add post device auth handler
nsklikas Mar 1, 2024
3bf1986
feat: add consent handler for accepting a user_code
nsklikas Mar 1, 2024
45db132
chore: add post_device_done to config schema
nsklikas Mar 7, 2024
8484d58
chore: add e2e tests
nsklikas Mar 11, 2024
7fb2d45
feat: token request handling for device flow
wood-push-melon Mar 23, 2024
f5ddf04
chore: update config
nsklikas Mar 21, 2024
f35cd27
fix: fix the OIDC token and refresh token issue for device flow
wood-push-melon Apr 11, 2024
efd42df
fix: update OpenID Connect session after user consent
wood-push-melon Apr 12, 2024
dbce6e3
fix: add GetDeviceCodeSessionByRequestID method
nsklikas Apr 15, 2024
a765730
fix: return client_id to post_device page
nsklikas Apr 15, 2024
9cbbdb4
fix: update existing device session
nsklikas Apr 15, 2024
10b66cc
fix: update tests
nsklikas Apr 15, 2024
4761c44
fix: add device auth endpoint in discovery metadata
nsklikas Apr 23, 2024
935ffa3
fix: make device grant lifetimes configurable
nsklikas Apr 25, 2024
bc51324
test: update sql fixtures
nsklikas Apr 29, 2024
ed2ccce
fix: perform device flow from CLI
nsklikas May 22, 2024
9bb1634
fix: wrap db calls in transaction
nsklikas Jul 30, 2024
1611d7f
chore: fix license
nsklikas Sep 25, 2024
eadbd60
chore: update sdk
nsklikas Sep 24, 2024
467091a
fix: duplicate user_code update
nsklikas Sep 26, 2024
dfa4c99
refactor: merge user and device code tables
nsklikas Nov 15, 2024
6309d8d
fix: create openid session when log in succeeds
nsklikas Nov 18, 2024
21c29d2
refactor: update device session persistence logic
nsklikas Nov 15, 2024
8da4859
fix: update oauth persister logic
nsklikas Dec 10, 2024
14cf7cd
fix: handle user_code collisions
nsklikas Jan 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .schema/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,11 @@
"description": "Sets the session cookie name. Use with care!",
"type": "object",
"properties": {
"device_csrf": {
"type": "string",
"title": "CSRF Cookie Name",
"default": "ory_hydra_device_csrf"
},
"login_csrf": {
"type": "string",
"title": "CSRF Cookie Name",
Expand Down Expand Up @@ -645,6 +650,14 @@
"examples": [
"https://example.org/my-custom-userinfo-endpoint"
]
},
"device_authorization_url": {
"type": "string",
"description": "A URL of the device authorization endpoint to be advertised at the OpenID Connect Discovery endpoint /.well-known/openid-configuration. Defaults to Ory Hydra's device authorizatoin endpoint at /oauth2/device/auth. Set this value if you want to handle this endpoint yourself.",
"format": "uri-reference",
"examples": [
"https://example.org/oauth2/device/auth"
]
}
}
}
Expand Down Expand Up @@ -803,6 +816,24 @@
"/ui/logout"
]
},
"device_verification": {
"type": "string",
"description": "Sets the device user code verification endpoint. Defaults to an internal fallback URL showing an error.",
"format": "uri-reference",
"examples": [
"https://my-logout.app/device_verification",
"/ui/device_verification"
]
},
"post_device_done": {
"type": "string",
"description": "Sets the post device authentication endpoint. Defaults to an internal fallback URL showing an error.",
"format": "uri-reference",
"examples": [
"https://my-logout.app/device_done",
"/ui/device_done"
]
},
"error": {
"type": "string",
"description": "Sets the error endpoint. The error ui will be shown when an OAuth2 error occurs that which can not be sent back to the client. Defaults to an internal fallback URL showing an error.",
Expand Down Expand Up @@ -947,6 +978,15 @@
"$ref": "#/definitions/duration"
}
]
},
"device_user_code": {
"description": "Configures how long device and user codes are valid.",
"default": "15m",
"allOf": [
{
"$ref": "#/definitions/duration"
}
]
}
}
},
Expand Down Expand Up @@ -1064,6 +1104,17 @@
}
}
},
"device_authorization": {
"token_polling_interval": {
"description": "Sets the starting token polling interval.",
"default": "5s",
"allOf": [
{
"$ref": "#/definitions/duration"
}
]
}
},
"grant": {
"type": "object",
"additionalProperties": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,8 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,8 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,8 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,8 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,8 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,8 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,8 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,8 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,8 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,8 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,8 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,8 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,8 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
},
"status": 200
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
},
"status": 200
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@
"jwt_bearer_grant_access_token_lifespan": "37h0m0s",
"refresh_token_grant_id_token_lifespan": "40h0m0s",
"refresh_token_grant_access_token_lifespan": "41h0m0s",
"refresh_token_grant_refresh_token_lifespan": "42h0m0s"
"refresh_token_grant_refresh_token_lifespan": "42h0m0s",
"device_authorization_grant_id_token_lifespan": "45h0m0s",
"device_authorization_grant_access_token_lifespan": "46h0m0s",
"device_authorization_grant_refresh_token_lifespan": "47h0m0s"
},
"status": 200
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
},
"status": 200
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
},
"status": 200
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,8 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,8 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,8 @@
"jwt_bearer_grant_access_token_lifespan": null,
"refresh_token_grant_id_token_lifespan": null,
"refresh_token_grant_access_token_lifespan": null,
"refresh_token_grant_refresh_token_lifespan": null
"refresh_token_grant_refresh_token_lifespan": null,
"device_authorization_grant_id_token_lifespan": null,
"device_authorization_grant_access_token_lifespan": null,
"device_authorization_grant_refresh_token_lifespan": null
}
24 changes: 24 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ type Client struct {
// - OpenID Connect Implicit Grant (deprecated!): `implicit`
// - Refresh Token Grant: `refresh_token`
// - OAuth 2.0 Token Exchange: `urn:ietf:params:oauth:grant-type:jwt-bearer`
// - OAuth 2.0 Device Code Grant: `urn:ietf:params:oauth:grant-type:device_code`
GrantTypes sqlxx.StringSliceJSONFormat `json:"grant_types" db:"grant_types"`

// OAuth 2.0 Client Response Types
Expand Down Expand Up @@ -379,6 +380,21 @@ type Lifespans struct {
//
// The lifespan of a refresh token issued by the OAuth2 2.0 Refresh Token Grant for this OAuth 2.0 Client.
RefreshTokenGrantRefreshTokenLifespan x.NullDuration `json:"refresh_token_grant_refresh_token_lifespan,omitempty" db:"refresh_token_grant_refresh_token_lifespan"`

// OAuth2 2.0 Device Authorization Grant ID Token Lifespan
//
// The lifespan of an ID token issued by the OAuth2 2.0 Device Authorization Grant for this OAuth 2.0 Client.
DeviceAuthorizationGrantIDTokenLifespan x.NullDuration `json:"device_authorization_grant_id_token_lifespan,omitempty" db:"device_authorization_grant_id_token_lifespan"`

// OAuth2 2.0 Device Authorization Grant Access Token Lifespan
//
// The lifespan of an access token issued by the OAuth2 2.0 Device Authorization Grant for this OAuth 2.0 Client.
DeviceAuthorizationGrantAccessTokenLifespan x.NullDuration `json:"device_authorization_grant_access_token_lifespan,omitempty" db:"device_authorization_grant_access_token_lifespan"`

// OAuth2 2.0 Device Authorization Grant Device Authorization Lifespan
//
// The lifespan of a Device Authorization issued by the OAuth2 2.0 Device Authorization Grant for this OAuth 2.0 Client.
DeviceAuthorizationGrantRefreshTokenLifespan x.NullDuration `json:"device_authorization_grant_refresh_token_lifespan,omitempty" db:"device_authorization_grant_refresh_token_lifespan"`
}

func (Client) TableName() string {
Expand Down Expand Up @@ -549,6 +565,14 @@ func (c *Client) GetEffectiveLifespan(gt fosite.GrantType, tt fosite.TokenType,
} else if tt == fosite.RefreshToken && c.RefreshTokenGrantRefreshTokenLifespan.Valid {
cl = &c.RefreshTokenGrantRefreshTokenLifespan.Duration
}
} else if gt == fosite.GrantTypeDeviceCode {
if tt == fosite.AccessToken && c.DeviceAuthorizationGrantAccessTokenLifespan.Valid {
cl = &c.DeviceAuthorizationGrantAccessTokenLifespan.Duration
} else if tt == fosite.IDToken && c.DeviceAuthorizationGrantIDTokenLifespan.Valid {
cl = &c.DeviceAuthorizationGrantIDTokenLifespan.Duration
} else if tt == fosite.RefreshToken && c.DeviceAuthorizationGrantRefreshTokenLifespan.Valid {
cl = &c.DeviceAuthorizationGrantRefreshTokenLifespan.Duration
}
}

if cl == nil {
Expand Down
2 changes: 2 additions & 0 deletions client/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/ory/fosite"
foauth2 "github.com/ory/fosite/handler/oauth2"
"github.com/ory/fosite/handler/rfc8628"
enigma "github.com/ory/fosite/token/hmac"
"github.com/ory/hydra/v2/jwk"
"github.com/ory/hydra/v2/x"
Expand All @@ -25,5 +26,6 @@ type Registry interface {
OpenIDJWTStrategy() jwk.JWTSigner
OAuth2HMACStrategy() foauth2.CoreStrategy
OAuth2EnigmaStrategy() *enigma.HMACStrategy
RFC8628HMACStrategy() rfc8628.RFC8628CodeStrategy
config.Provider
}
Loading
Loading