Skip to content

Allow user to override getToken function. #164

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

TheCynosure
Copy link

@TheCynosure TheCynosure commented Jan 17, 2025

Description

Allows the user to specify a custom token location for retrieving the authorization/access_token JWT. Currently, the getToken function is fixed and the user is only able to use one of the pre-determined locations ("authorization" for headers, "access_token" for query/body) for their authorization tokens.

Now the developer can specify whatever location they desire. This is asked for in #147 and I need this as well.

This should not be a breaking change.

References

#147

Testing

Unit tests were added for this functionality. Should be verifiable with npm test. Tested on NodeJS v18.19.1, Ubuntu 24.04.

  • This change adds test coverage for new/changed/fixed functionality

Documentation

Documentation was updated with npm run docs, it led to more changes than I expected, but it seems to be from a commit hash reference changing.

Checklist

  • I have added documentation for new/changed functionality in this PR or in auth0.com/docs
  • All active GitHub checks for tests, formatting, and security are passing
  • The correct base branch is being used, if not the default branch

@TheCynosure TheCynosure requested a review from a team as a code owner January 17, 2025 01:20
@nandan-bhat
Copy link
Contributor

nandan-bhat commented Feb 28, 2025

Hi @TheCynosure,

Can you please sign the commits ? Currently the commits do not have verified signatures.

Reference: https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits

* Function to get token from request.
* Defaults to getToken from 'oauth2-bearer'.
*/
getToken?: typeof getToken;
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we really need to completely override the getToken method?

Wouldn't it be possible to simply extract the token from the specified location and return it instead?

interface AuthOptions {
  tokenLocations?: ('header' | 'query' | 'body')[];
  // other options...
}

Copy link
Author

Choose a reason for hiding this comment

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

I updated the PR @nandan-bhat to allow a user to specify a singular tokenLocation. Multiple token locations seemed to get confusing as it could apply to multiple locations.

@@ -84,7 +89,7 @@ export const auth = (opts: AuthOptions = {}): Handler => {

return async (req: Request, res: Response, next: NextFunction) => {
try {
const jwt = getToken(
const jwt = (opts.getToken ?? getToken)(
Copy link
Contributor

Choose a reason for hiding this comment

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

How about pass the tokenLocations and implement the logic inside getToken method to return the token from the location specified in tokenLocations ?

@nandan-bhat
Copy link
Contributor

nandan-bhat commented Feb 28, 2025

Hey @TheCynosure,

I think we can make this flexible by adding an optional tokenLocation property to AuthOptions. This way, the token can be retrieved from the specified location without overriding the entire getToken method.

If tokenLocation isn't provided, the behavior would remain the same as it is now. This keeps things backward-compatible while allowing customization where needed.

What do you think?

@TheCynosure
Copy link
Author

@nandan-bhat I liked the simplicity of overriding getToken and the flexibility it offered. But, at the same time it is providing more room for errors to be introduced by the end user. I ended up allowing the user to specify a single custom "tokenLocation" which is checked for in the headers, query params, and body.

If unspecified, the code checks the default locations for headers, query params, and body.

@nandan-bhat
Copy link
Contributor

nandan-bhat commented Mar 4, 2025

Hey @TheCynosure,

I have already gone through the PR description, but I’d love to understand your specific use case better. What’s the reason for needing to customize the authorization and access_token keys ?

If the goal is simply to meet the requirement in #147, wouldn’t it be enough to define tokenLocation?: "header" | "body" | "query"; and then retrieve the token based on that ?

With Express: If your environment doesn't allow sending access_token as a query or body parameter, you can work around it by using a custom middleware. This lets you send any query parameter you prefer and then map it to access_token before it reaches the auth({...}) method.

I’d love to understand your use case better since I don’t have full context on what this PR is addressing. Could you share more details on the specific problem it’s solving ?

Let me know your thoughts!

* Header, Body, or Query Parameter location to retrieve the JWT from.
* Defaults to "authorization" header and "access_token" body and query parameter.
*/
tokenLocation?: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

@TheCynosure

I’m curious, why is tokenLocation defined as a flexible string instead of something stricter like this?

tokenLocation?: "header" | "body" | "query";

It looks like the intention isn’t just to specify where the token should be retrieved from, but also to allow customization of the query parameter name. That seems like a slightly different requirement than what was discussed in reference #147.

@TheCynosure
Copy link
Author

Hey @TheCynosure,

I have already gone through the PR description, but I’d love to understand your specific use case better. What’s the reason for needing to customize the authorization and access_token keys ?

If the goal is simply to meet the requirement in #147, wouldn’t it be enough to define tokenLocation?: "header" | "body" | "query"; and then retrieve the token based on that ?

With Express: If your environment doesn't allow sending access_token as a query or body parameter, you can work around it by using a custom middleware. This lets you send any query parameter you prefer and then map it to access_token before it reaches the auth({...}) method.

I’d love to understand your use case better since I don’t have full context on what this PR is addressing. Could you share more details on the specific problem it’s solving ?

Let me know your thoughts!

Hey @nandan-bhat,
My use case is that I have two authorization Jwts. One from Okta and another from a different authority. I would like to use this library to validate both Jwts. For example one is in the "authorization" header and another is in the "authorization-second" header.

And yeah good callout on not solving #147. I think the original solution of overriding getToken completely solved both, but now this approach only solves my issue.

@nandan-bhat
Copy link
Contributor

nandan-bhat commented Mar 4, 2025

Hey @TheCynosure,
I have already gone through the PR description, but I’d love to understand your specific use case better. What’s the reason for needing to customize the authorization and access_token keys ?
If the goal is simply to meet the requirement in #147, wouldn’t it be enough to define tokenLocation?: "header" | "body" | "query"; and then retrieve the token based on that ?
With Express: If your environment doesn't allow sending access_token as a query or body parameter, you can work around it by using a custom middleware. This lets you send any query parameter you prefer and then map it to access_token before it reaches the auth({...}) method.
I’d love to understand your use case better since I don’t have full context on what this PR is addressing. Could you share more details on the specific problem it’s solving ?
Let me know your thoughts!

Hey @nandan-bhat, My use case is that I have two authorization Jwts. One from Okta and another from a different authority. I would like to use this library to validate both Jwts. For example one is in the "authorization" header and another is in the "authorization-second" header.

And yeah good callout on not solving #147. I think the original solution of overriding getToken completely solved both, but now this approach only solves my issue.

@TheCynosure ,

What do you think about these approaches?

Option 1: Use the "Authorization" header for everything – Okta and other providers both use it, and I’d pick the right middleware based on another header, like auth-provider: okta.

Option 2: Tweak the headers before calling auth({}) – Basically, modify them upfront so they work smoothly with auth({}) without extra handling later.

I understand that overriding getToken is a more flexible solution compared to these workarounds. However, since we need to discuss it internally with other Auth0 members before moving forward, I’m suggesting these temporary alternatives in the meantime.

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.

2 participants