-
Notifications
You must be signed in to change notification settings - Fork 503
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 JWTAuthenticator.Authenticate #18052
Conversation
9 similar comments
@SimonRichardson for the two workflows failing:
Do you have suggestions to fix the issues? |
/build |
The new go release caused this. I'll need to workout what the fix is. |
We need to bump the go version in the go.mod file. @hpidcock have you already fixed this, or do we want to do this here? |
@SimonRichardson do you have any update on this? If there is something I can do to help let me know :) |
6fc8960
to
25f94bf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd want tooling to be added that can craft me a JWT token I can use for curl. I've had that in previous companies I've worked for, and it can be invaluable.
Could be a simple as:
go run ./scripts/auth/jwt.go ....
if authHeader == "" { | ||
return authentication.AuthInfo{}, errors.NotFoundf("authorization header missing") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a bad request. We might have to do some additional plumbing to get this to work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, as described in the description, this change is to comply with the for loop apiserver/stateauthenticator/auth.go:21
. If there is any error besides not-found or not-implemented the authentication fails and it doesn't try the next authenticator.
I can change and add the not-valid to the for logic, what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I shot the original comment too early.
I'm not sure where your link leads to?
juju/apiserver/stateauthenticator/auth.go
Line 21 in bc3a4ce
"github.com/juju/juju/apiserver/apiserverhttp" |
Do you mean?
juju/apiserver/authentication/http.go
Lines 20 to 31 in bc3a4ce
func (s HTTPStrategicAuthenticator) Authenticate(req *http.Request) (AuthInfo, error) { | |
for _, authenticator := range s { | |
authInfo, err := authenticator.Authenticate(req) | |
if errors.Is(err, errors.NotImplemented) { | |
continue | |
} else if errors.Is(err, errors.NotFound) { | |
continue | |
} else if err != nil { | |
return AuthInfo{}, err | |
} | |
return authInfo, nil | |
} |
If we return errors.BadRequest
then we need to understand what to do there. I believe if we get a errors.BadRequest
then we should return that directly to the client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just want to clarify, that we should ensure that we don't leak information about the user, just that JWT is malformed if the JWT header was sent. Otherwise returning NotFound is valid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, it is the code I was referring to.
In this current implementation we return:
- not found if the Authorization header is missing -> go to next authenticator
- not found if the Authorization header is there, but it is not formatted as "Bearer <>" -> go to next authenticator
- another error if the jwt cannot be parsed -> return the error to the user
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that's fine. I'm happy with that logic. Leave as not found error, given the scenarios you've described. Can you document the expectations of that in the HTTPStrategicAuthenticator.Authenticate
method, and validate the tests work as expected according to those expectations?
Thanks for this @SimoneDutto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perfect.
the behavior is described at the interface level, a few lines above the authenticate method
juju/apiserver/authentication/http.go
Lines 13 to 16 in bc3a4ce
// HTTPStrategicAuthenticator is responsible for trying multiple Authenticators | |
// until one succeeds or an error is returned that is not equal to NotFound or | |
// NotImplemented. | |
type HTTPStrategicAuthenticator []HTTPAuthenticator |
I've added some tests for the HTTPStrategicAuthenticator
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing thank-you.
Regarding the jwt tooling, I'll try to work out something. |
f4a4bdc
to
7036128
Compare
as discussed with @SimonRichardson, the JWT tooling is not needed for this PR. |
/build |
/merge |
#18155 Forward merge: - #18154 - #18022 - #17699 - #18095 - #18052 - #18073 - #18091 - #18083 Conflicts: worker/uniter/runner/context/context_test.go version/version.go scripts/win-installer/setup.iss snap/snapcraft.yaml Note: this PR also has a small change for the #18154 to include the checksum for the idempotent secret feature.
Hi, I am Simone from the JaaS Team.
This pr implements the
JWTAuthenticator.Authenticate()
method.It is needed for JaaS to authenticate to HTTP endpoints via JWT similarly as it is already doing it for websockets endpoints.
For example, we are currently authenticated via basic-auth for the http endpoint handling the debug-logs (PR), and we would like to switch to JWT auth.
Implementation
The
Authenticate
method extracts the Bearer token from the Authorization header and validates the jwt.Since the
HTTPStrategicAuthenticator
is looping around multiple http authenticators (apiserver/stateauthenticator/auth.go:21
), and going to the next if the error is "not found" or "not implemented", to allow both basic-auth and jwt authentication to work I needed to changeapiserver/stateauthenticator/auth.go:265
to return a NotFound error in case of missing basic-auth header.Checklist
QA steps
After bootstrapping a controller with jwt authenticator properly configured.
Issuing this command
Documentation changes