Support OpenID and 3rd party IdTokens with cookie-less authentication
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 1.4k
- Forks
- 97
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 2
Description
There are probably quite a few parts in this issue, I totally see those as separate small PRs / issues.
Context
Currently, auth package supports various OAuth2 providers and acts as a OAuth2 Authorization Server / proxy (without strongly committing to RFC) by issuing self-signed ID tokens based on info provided by /userinfo response, which are passed via a cookie, with extra XSRF protection.
Proposal
Support OpenID providers and ID tokens issued by an external identity provider as authentication tokens. In this scenario, the server won't have private keys and won't issue ID tokens itself. Potentially support OpenID Connect Discovery protocol. Unlike general OAuth2 spec, OpenID supports issuing signed ID tokens bound to a particular user, so these tokens can be used for authentication.
How I see the potential configuration:
// code below will fetch OpenID Connect Discovery config
// from https://accounts.google.com/.well-known/openid-configuration
// then it'll load keys from "jwks_uri" endpoint and store them under "google" provider
service.AddOpenIDProvider("google", "https://accounts.google.com", "client-id", "client-secret")
m := service.Middleware()
router := chi.NewRouter()
// setup auth routes
authRoutes, avaRoutes := service.Handlers()
// for OpenID providers, /auth handler won't just fetch access token + userinfo,
// but will actually request a signed ID token from the provider.
// This token can be then passed to the client as is, as it is signed already
// and we have public keys for validate it.
router.Mount("/auth", authRoutes) // add auth handlers
router.Mount("/avatar", avaRoutes) // add avatar handler
// m.OpenIDAuth won't use own keys defined in opts.SecretReader, but instead will use public keys loaded before
// the provider can be identified either by "iss" claim or manually configured, i.e. m.OpenIDAuth("google")
// Also, OpenIDAuth shouldn't require a cookie, but Authorization: Bearer <jwt> header to work.
router.With(m.OpenIDAuth).Get("/api-endpoint", protectedRouteHandler) // protected api
router.With(m.OpenIDAuth(func(claims token.Claims) bool {
// do any authorization checks on the token claims, e.g. Role
})).Get("/api-endpoint", protectedRouteHandler) // protected api
With OpenIDAuth authentication middleware, the server should act as a OAuth2 Resource Server, i.e. to expect Authorization: Bearer <jwt> header and use that for authentication.
Having this would allow:
- Remove need in issuing auth (ID) tokens, as well as managing signing keys
- Easy integration with new providers
- Unify user / API authentication middleware (by using
Authorizationheader) - Multiple services using the same auth middleware configuration without sharing secrets
Considerations:
- Some parts of configuration options are irrelevant for OpenID providers, where
authis only acting as a authentication proxy basically. Likeopts.ClaimsUpdaterwon't work - since we don't have private keys, we can't modify claims. Probably OpenID should have own configuration options? - How to pass a signed ID token to the client? I think the cookie approach can still be used, but instead of checking the cookie,
Authorizationheader should be checked, which is set from the cookie. This kind of gives XSRF protection for free.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the auth package's existing OAuth2 handlers, middleware, provider configuration, and token validation flow. Break the proposal into separate changes for OpenID discovery and keys, bearer-token authentication, and provider-issued ID tokens; done means each chosen part has focused tests covering configuration, validation, and the Authorization header path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, authentication, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100