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

Support alternative token location #271

Merged
merged 15 commits into from
Oct 9, 2019

Conversation

kubadz
Copy link
Contributor

@kubadz kubadz commented Oct 2, 2019

Related issue

#257

Proposed changes

Add additional optional configuration to jwt and oauth2_introspection authenticators allowing to set from where (which header or query parameter) the token should be received. The configuration is a token_from field in per-rule-configuration, as described in a linked issue.

Checklist

  • I have read the contributing guidelines
  • I have read the security policy
  • I confirm that this pull request does not address a security
    vulnerability. If this pull request addresses a security vulnerability, I
    confirm that I got green light (please contact
    [email protected]) from the maintainers to push
    the changes.
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation within the code base (if appropriate)
  • I have documented my changes in the
    developer guide (if appropriate)

Further comments

QueryParameter *string `json:"query_parameter"`
}

func BearerTokenFromRequest(r *http.Request, tokenLocation *BearerTokenLocation) string {
Copy link
Member

Choose a reason for hiding this comment

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

Would it make sense to test this independently?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah. That might be a good idea :)
I added tests.

helper/bearer.go Outdated
if tokenLocation.Header != nil {
token = r.Header.Get(*tokenLocation.Header)
} else if tokenLocation.QueryParameter != nil {
token = r.FormValue(*tokenLocation.QueryParameter)
Copy link
Member

Choose a reason for hiding this comment

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

same here:

Suggested change
token = r.FormValue(*tokenLocation.QueryParameter)
return r.FormValue(*tokenLocation.QueryParameter)

helper/bearer.go Outdated
var token string
if tokenLocation != nil {
if tokenLocation.Header != nil {
token = r.Header.Get(*tokenLocation.Header)
Copy link
Member

Choose a reason for hiding this comment

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

Wouldn't it make more sense to return the value here directly?

Suggested change
token = r.Header.Get(*tokenLocation.Header)
return r.Header.Get(*tokenLocation.Header)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can't return the value directly there, as in your suggestion, because we need to return only the token without the "bearer" part. However, I thought about moving lines 49-53 to a separate function. Then the line of your suggestion would look like:

return getToken(r.Header.Get(*tokenLocation.Header))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What do you think?

Copy link
Member

Choose a reason for hiding this comment

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

The bearer is only relevant when the header is Authorization as as means of switching authorization modes (e.g. basic, bearer, ...).

However, an explicit query parameter such as ?token=1234 would not include the bearer instruction as the parameter is already explicitly bound to a token. The same applies if we define a custom header such as X-MyApplication-AuthToken. Here too, the context is explicit and clear.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok. Then of course we can do it like you suggested :)
From the issue and comments I understood that we only want to change location of the token in the means of changing Header name or switching to query param, without tampering with the value of the Header.
So for example you can change header name in some proxy without changing the value of header itself.

Copy link
Member

Choose a reason for hiding this comment

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

I think in query param schema should not be present in the value but in custom header it coud be, this gives more guarantee/flexibility that some libs in developer application will still work. OAuth for example expects Bearer scheme

That would be two authenticators with two separate custom headers IMO

Copy link

Choose a reason for hiding this comment

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

@aeneasr We do not give the possibility to override the scheme and IMO it should remain as it is but with the option to use different header

Copy link
Contributor Author

@kubadz kubadz Oct 8, 2019

Choose a reason for hiding this comment

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

@aeneasr the last word is yours 😄 Do you want the "bearer" in custom header value to be optional, required or not valid?

Copy link
Member

@aeneasr aeneasr Oct 8, 2019

Choose a reason for hiding this comment

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

I think it's very confusing to have the "bearer" in the custom header and the query parameter. If you look at the documentation it also does not become very clear. This is something I believe will make things very awkward when people are trying to use these features as I've never ever in my life have seen something like X-Token-Auth: bearer bla nor ?token=bearer%20bla. So please remove the "bearer" splitting for these two parameters and, if unclear, explicitly document it with examples in the docs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, done 😄

token = r.Header.Get(*tokenLocation.Header)
} else if tokenLocation.QueryParameter != nil {
token = r.FormValue(*tokenLocation.QueryParameter)
}
Copy link
Member

Choose a reason for hiding this comment

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

Is it possible that both if / else if do not get executed? Then token would be empty.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is not possible, as JSON schema for jwt and oauth2_introspection authenticators would not allow for that.

Copy link
Member

Choose a reason for hiding this comment

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

Can we make this explicit in the code by simply doing a if/else?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can, but if somehow QueryParameter would be a nil, than the program will crash on dereferencing a nil pointer. With "else if" the function will simply return an empty string, like if there was no token in the configured header/query parameter (what may be a proper behavior if there was "alternative token location" set, but not configured - even though with the current schema it is not possible).

I see an alternative solution here: returning an error saying that rule is misconfigured. But I would have to add error handling in the places where this function is called.

What do you think?

Copy link
Member

Choose a reason for hiding this comment

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

Ok, how about simply falling back to the authorization header in the case where both are nil?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, done

@aeneasr aeneasr merged commit fc85ac8 into ory:master Oct 9, 2019
@kubadz kubadz deleted the alternative-token-location branch October 9, 2019 11:25
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.

4 participants