-
Notifications
You must be signed in to change notification settings - Fork 8
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
Css 6646/callback endpoint #1170
Css 6646/callback endpoint #1170
Conversation
As discussed on call, we integration test only the handler and avoid mocks to see the behaviour is as expected. This is also true when we come to implements the callback logic and are required to start the flow from scratch. The current test in auth_handler_test will be updated to cover the entire flow when implementing /callback. As for the state todo, I need to see how to track the state between requests and the TODO will be completed in the /callback PR. 6646
…ssions) This PR includes a small refactor to the admin device flow, such that it can share the same identity update logic within the browser flow.
…and auth svc not nill
… css-6646/callback-endpoint
// the final callback to the dashboard emulating an endpoint. See setupTestServer | ||
// where we create an additional handler to simulate the final callback to the dashboard | ||
// from JIMM. | ||
func TestBrowserAuth(t *testing.T) { |
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 only tests the "happy path".. we would need additional tests..
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.
Yeah... But I'm not sure what or how?
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.
exchange fails, update identity fails, etc..
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'll try do some more where we check this stuff before merging this PR, just might need to experiment a little and then I'll @ you
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.
@@ -203,6 +241,34 @@ func (as *AuthenticationService) VerifySessionToken(token string, secretKey stri | |||
return VerifySessionToken(token, secretKey) | |||
} | |||
|
|||
// UpdateIdentity updates the database with the display name and access token set for the user. | |||
// And, if present, a refresh token. | |||
func (as *AuthenticationService) UpdateIdentity(ctx context.Context, email string, token *oauth2.Token) error { |
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.
is this unit tested?
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.
also.. it doesn't make sense to pass in email as a separate parameter.. you could just call
idToken, err := as.ExtractAndVerifyIDToken(ctx, token)
if err != nil {
writeError(ctx, w, http.StatusBadRequest, err, "failed to extract and verify id token")
return
}
email, err := email(idToken)
here to get the email from the token
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.
It isn't tested individually it's part of the TestDevice, I need to come back and mock all of this out afterwards. That's the plan anyways, so I guess view the tests here as temporary, I just written them to help develop. And it's separate as I think the extracting email from a field that can error out is better done outside of the function? Happy to call .Email() within updateidentity but I feel this is clearer / more obvious?
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.
also in next pr we actually use the email in another function within the handler, so i'll leave this as is
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.
why??
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.
We pass it over to the session creation
// If the session is empty, it'll just be an empty session, we only check
// errors for bad decoding etc.
session, err := oah.SessionStore.Get(r, "jimm-browser-session")
if err != nil {
writeError(ctx, w, http.StatusBadRequest, err, "failed to get session")
}
session.Values["jimm-session"] = email
AuthCodeURL() string | ||
Exchange(ctx context.Context, code string) (*oauth2.Token, error) | ||
ExtractAndVerifyIDToken(ctx context.Context, oauth2Token *oauth2.Token) (*oidc.IDToken, error) | ||
Email(idToken *oidc.IDToken) (string, error) |
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.
Email does not need to be a method of the authenticator.. it can be an independent function because it just extracts an email from the id token that's passed in
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.
Answered in the other comment why I did this
@@ -71,6 +87,7 @@ func NewAuthenticationService(ctx context.Context, params AuthenticationServiceP | |||
RedirectURL: params.RedirectURL, | |||
}, | |||
sessionTokenExpiry: params.SessionTokenExpiry, | |||
db: params.Store, |
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.
some validation of input parameters should be done here, no? like.. store should not be nil, sessionTokenExpiry should not be 0.. i'm sure there's other validation we could do
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 feel like validation should be done at the service.go level, but happy to add more in?
u := &dbmodel.Identity{ | ||
Name: email, | ||
} | ||
// TODO(babakks): If user does not exist, we will create one with an empty |
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.
Should we create a ticket for this and link it here?
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 one might exist... i am a bit confused by it though. trhis was more babaks suggestion
return nil, errors.E("nil authenticator") | ||
} | ||
if dashboardFinalRedirectURL == "" { | ||
return nil, errors.E("final redirect url not specified") |
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 is good enough, but I think we should give it another thought. All the tests are created with "no dashboard required for this test", which could have been avoided if this was not required here as we return an error.
Moreover, checking on empty strings shouldn't be enough, we need to actually verify the url is parseable, valid, and reachable. If not, return an error, too
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 is because the auth handler has validation, which I agree with Ales it was necessary, just our other handlers don't have the same validation... Because we embed into jimm a lot we end up with this polluted mess of creating stuff for the sake of creating it. And ah yeah definitely, I'll add a url parse to next PR totally agree.
@@ -56,6 +56,7 @@ func TestDefaultService(t *testing.T) { | |||
Scopes: []string{oidc.ScopeOpenID, "profile", "email"}, | |||
SessionTokenExpiry: time.Duration(time.Hour), | |||
}, | |||
DashboardFinalRedirectURL: "<no dashboard needed for this test>", |
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 is what I was referring to
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.
Yeah I know this one...
@@ -406,6 +413,7 @@ func TestThirdPartyCaveatDischarge(t *testing.T) { | |||
Scopes: []string{oidc.ScopeOpenID, "profile", "email"}, | |||
SessionTokenExpiry: time.Duration(time.Hour), | |||
}, | |||
DashboardFinalRedirectURL: "<no dashboard needed for this test>", |
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.
why force it if it is never used in the tests?
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.
Other comment explains
Description
feat(browser flow for dashboard): implements browser flow (without sessions)
Engineering checklist
Check only items that apply
Test instructions
Notes for code reviewers