-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Best practice? Optional (single) endpoint authentication #4842
Comments
Umm. I would think an endpoint that requires authentication to protected resources shouldn't allow anyone on the internet to access that specific resource, so I am having trouble understanding the special scenario for such a need. Perhaps you can elaborate? thx. @raymondfeng , do you have some thoughts on this? thx. |
Keyword being optional rather than required on the standard authentication via say JWT. A more sensible use-case would be using a separate token(say emailed to user for password reset) alongside the JWT bearer token. For example: @authenticate('jwt-optional')
@patch('/users/{id}/password')
async passwordUpdate(
@requestBody({ // new password }}
@inject(SecurityBindings.USER) currentUser: UserProfile,
@param.path.string('id') id: string,
@param.query.string('key') keyId?: string,
): User {
if (!currentUser.id) {
const keyFound = getKey(keyId);
if (!keyFound) {
// throw auth error
}
}
const userId = currentUser.id ?? keyFound.id;
// ... update user
// ... return updated user (simplified, assuming password returned for example)
} Would this be recommended to completely encapsulate in an auth strategy? Or used with extreme caution.... Thanks for your advice. |
@bajtos or @raymondfeng , what is your opinion on this scenario? |
I'm thinking the following would be a move in a better direction... Would it be an idea to use export class JWTOrKeyAuthenticationStrategy implements AuthenticationStrategy {
name = 'jwt-key';
constructor(
@inject(TokenServiceBindings.TOKEN_SERVICE)
public tokenService: TokenService,
@inject(KeyServiceBindings.KEY_SERVICE)
public keyService: AccountKeyService,
) {}
async authenticate(request: Request): Promise<UserProfile | undefined> {
const token: string | undefined = this.extractCredentials(request);
const key: string | undefined = this.extractKey(request);
if (!token && !key) {
throw new HttpErrors.Unauthorized(
'Authorization cannot find JWT or Key.',
);
}
const accKey = key ? await this.keyService.getKey(key) : undefined;
const userProfile: UserProfile = {
[securityId]: '',
...(token && (await this.tokenService.verifyToken(token))),
...(accKey && {reqKey: accKey}),
};
return userProfile;
}
extractCredentials(request: Request): string | undefined {
if (!request.headers.authorization) return undefined;
const authHeaderValue = request.headers.authorization;
if (!authHeaderValue.startsWith('Bearer')) return undefined;
const parts = authHeaderValue.split(' ');
if (parts.length !== 2) return undefined;
const token = parts[1];
return token;
}
extractKey(request: Request): string | undefined {
if (!request.query['key']) return undefined;
const key = request.query['key'];
// account key is uuid with 36 chars
if (key.length !== 36) {
return undefined;
}
return key;
}
} |
@dougal83 Do you use authentication for personalization in this case? |
@raymondfeng Yes, that was the idea. Something non essential that could pull up customised data if available for the user. |
I think #5735 will address the issue. |
@jannyHou Yes, it looks like it will solve the issue supplying multiple strategies. Feel free to close this issue at your convenience. |
Closing per the above comment. |
Its really much easier, you can give a 2nd argument like this to inject: |
Simply put, how is it best to create an endpoint that allows both anonymous and authenticated access. Should this pattern be avoided? Is there a better way?
Use case: the same interface to create a comment anonymously or with username appended.
Example (NOT FOR PRODUCTION):
Optional JWT Strategy:
tag: @emonddr
The text was updated successfully, but these errors were encountered: