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(auth/oidc): OIDC authentication method support #1197

Merged
merged 17 commits into from
Dec 22, 2022
Merged

Conversation

GeorgeMac
Copy link
Member

@GeorgeMac GeorgeMac commented Dec 6, 2022

Fixes FLI-48
Fixes FLI-49

This implements the OIDC authorize URL and callback operations. Initially, just for the single provider, Google.
It uses HashiCorp cap as the wrapper around the Go OIDC library and Googles OAuth lib.
This library has the added benefit of a nice testing authorization service implementation.

The two operations implemented in this PR are:

  • AuthorizeURL, which returns an authorize URL for the configuration associated with the requested provider.
  • Callback, which handles exchanging an authentication code to verify authenticity and acquire an id_token. Once acquired, a Flipt client token is established with the user's metadata.

Additionally, there are a number of utility middlewares and gRPC gateway options.
These additions ensure that when interacting with the OIDC authentication method, that the resulting client token is automatically established as an HTTP cookie. This is to support browser sessions.

Update:

This is now flexible enough to support various generic OIDC providers.
This is after merging in #1223

@codecov-commenter
Copy link

codecov-commenter commented Dec 8, 2022

Codecov Report

Merging #1197 (f3709d5) into main (b4dc11f) will decrease coverage by 0.13%.
The diff coverage is 81.08%.

@@            Coverage Diff             @@
##             main    #1197      +/-   ##
==========================================
- Coverage   80.19%   80.05%   -0.14%     
==========================================
  Files          39       41       +2     
  Lines        2842     3113     +271     
==========================================
+ Hits         2279     2492     +213     
- Misses        459      499      +40     
- Partials      104      122      +18     
Impacted Files Coverage Δ
internal/server/auth/method/oidc/server.go 67.52% <67.52%> (ø)
internal/config/authentication.go 83.33% <77.77%> (-5.04%) ⬇️
internal/server/auth/method/oidc/http.go 85.55% <85.55%> (ø)
internal/config/config.go 88.35% <97.10%> (+3.17%) ⬆️
internal/server/middleware/grpc/middleware.go 57.57% <100.00%> (-1.73%) ⬇️

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

if v.GetBool(fmt.Sprintf("authentication.methods.%s.enabled", k)) {
method["cleanup"] = map[string]any{
"interval": time.Hour,
"grace_period": 30 * time.Minute,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

outside of the scope of this PR, but we should also track modifying the cue and jsonschema schemas for these config additions, as well as docs changes

Copy link
Member Author

@GeorgeMac GeorgeMac Dec 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah good shout. Is this something we could potentially add as a CI step?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FLI-117

// appropriate state parameter. It does so by wrapping any provided state parameter
// in a JSON object with an additional cryptographically-random generated security
// token. The payload is then encoded in base64 and added back to the state query param.
// The payload is then also encoded as a http cookie which is bound to the callback path.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

love these docs/comments 🤩

})
if err != nil {
return nil, err

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

// with the login form.
// It collecs the hidden values into a url.Values so that we can post the form
// using our Go client.
func parseLoginFormHiddenValues(r io.Reader) (url.Values, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function is wild

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😭 It definitely either sits-on or leaps over the line of acceptability 😂

I wanted to avoid bringing in more dependencies if I could. I just need to pull a particular form's hidden inputs out of an HTML page. But perhaps using a library would make this a lot more digestible.
What I really wanted was that test library to offer a way to get the code parameter without parsing HTML. I just haven't found it yet.
I guess, at-least, this is a little closer to what a user in a browser would do. Slightly more representative.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

haha totally understand. just saw html parsing as was like 🤯

feat(auth/oidc): implement authorize and callback

refactor(oidc): switch to hashicorp/cap package

test(oidc): add extra logging context for failure in CI

chore: more test logging context

chore: logging context around client cookie jar contents

chore: print entire cookie jar

fix(oidc): test use localhost over ip for cookie jar interactions

chore: appears the linters

refactor(internal/cmd): flatten bootstrapping package into one
@GeorgeMac GeorgeMac marked this pull request as ready for review December 12, 2022 19:20
@GeorgeMac GeorgeMac requested a review from a team as a code owner December 12, 2022 19:20
@GeorgeMac GeorgeMac changed the title draft(auth/oidc): complete implementation of the OIDC authentication method feat(auth/oidc): OIDC authentication method support Dec 12, 2022
Copy link
Collaborator

@markphelps markphelps left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!! this is huuuge

just one minor question/comment about error helpers

internal/server/evaluator.go Outdated Show resolved Hide resolved
GeorgeMac and others added 5 commits December 13, 2022 17:05
* feat(oidc): support generic OIDC providers

* refactor(config): support maps with keys containing underscore

* chore: appease the linters

* chore(config): update doc string

Co-authored-by: Mark Phelps <[email protected]>

* chore(config): update bind function doc

* feat(oidc): add more standard OIDC claims

* chore(oidc): remove redundent return statement

Co-authored-by: Mark Phelps <[email protected]>
@GeorgeMac GeorgeMac requested a review from markphelps December 21, 2022 10:21
Copy link
Collaborator

@markphelps markphelps left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤩

@GeorgeMac GeorgeMac merged commit 2ca03a7 into main Dec 22, 2022
@GeorgeMac GeorgeMac deleted the gm/oidc-google branch December 22, 2022 10:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants