createParamDecorator VS CanActivate in Nestjs for authorization - nestjs

I'm trying to authorize users based on their permissions. Is there any difference in functionality between using createParamDecorator and CanActivate method?
export const GetUser = createParamDecorator((data: string, ctx: ExecutionContext) : User => {
const request = ctx.switchToHttp().getRequest();
const user = request.user;
const permissions = user.permissions
for(var i = 0; i < permissions.length; i++){
if(permissions[i].name === data)
return user;
}
throw new NotFoundException()})

These are absolutely not equivalent approaches, and should not be considered as such. The createParamDecorator is supposed to be an easy way to tell Nest how to inject a custom value (e.g. req.user instead of having to do #Req() { user }). It was never meant to be used for authorization, and while you can, it will most likely lead to very weird stack traces.
Guards, on the other hands, were made for authentication and authorization of the request. You can set metadata on a handler (e.g. what roles are allowed), read them with the Reflector, and then apply the conditional logic of if the request is valid or not. You're also able to use dependency injection on guards to add things like your database connection and get a full user from the database from an ID, which isn't possible in the createParamDecorator.
Lastly, in guards you can throw any error you want, or you can return false and get back a 403 by Nest's design.
Is there any difference in functionality...?
As mentioned, the dependency injection. It's also easier to test guards, in my opinion. But that's me.

Related

NestJS: Authorization based on instances property best practice

I need authorization in NestJS based on instances property.
Ex. user can update only his own articles.
Is there another way despite defining the logic in each services? ( I know it is possible using CASL )
Not having a global guard will facility errors, and everything is authorized by default unless add logic on the service.
What about creating a function that takes the request, the model and the name of the proprety and use it wherever you want ?
const verifAuthorization = (
req: Request,
propName: string,
model: any
): void => {
const sender: User = req.user;
if (!sender) {
throw new BadRequestException("there is no user in the token");
}
if (!sender._id.equals(model[propName])) {
throw new UnauthorizedException();
}
};
Yes ! you will call it in every service you want to check the authorization in, but it will save you a lot of time and code

What is the best practice to have a variable which lives for application lifetime in Node.js?

I am developing a web service 'A' using Node.js, which communicate with an another service 'B'. A needs to get an access token from B at the beginning, and it needs to refresh it when the token expires.
I am not very familiar with Node.js, I need to store access token and refresh token comes from B and refresh them time to time, but I am not sure if there are global variables to do this. For example, in Flask I would have kept my tokens in app['tokens'] and could be update it.
Basically what I want to do is to have a B class and a global object of B, B will have accessToken and refreshToken fields, obj.sendRequest({requestInfo}) will send a request to B service by checking expiration time of tokens and refresh them if necessary.
What is the best practice to overcome such a problem in Node.js?
From your question I don't see if you are using TypeScript or not. I highly recommend it, but it is not required. I will give you my answer with a TypeScript example because it is easier to read and understand (I think). Adapting it to pure JS should be easy.
class ApiService {
private accessToken?: string
private accessTokenExpires?: Date
private async getAccessToken(): Promise<void> {
const apiResult = await GET_TOKEN_FROM_API
this.accessToken = apiResult.access_token
this.accessTokenExpires = apiResult.access_token_expires
}
public async GetItem(id: string): Promise<Item> {
if (!this.accessToken || this.accessTokenExpires < new Date()) {
await this.getAccessToken()
}
return GET_ITEM_FROM_API
}
}
export let itemService = new ItemService()
export function mockitemService(mock: any) {
itemService = mock
}
at the place where you want to use the class you can
import { itemService } from './services/item'
const item = itemService.getItem('123')
Using ServiceClasses like this makes easier to maintain the code later or to write tests with mocked data sources.

Convert NodeJS asynchronous code to Spring Project Reactor

I have below NodeJS code:
// req and resp are http request, response objects
var uri = req.getURI()
var pageView = new PageView(uri)
var token = req.token
if (token) {
UserRepository.findByToken(token, function(notFound, user){
if(notFound) { // means user not found by specified token
var newUser = new User('John Doe')
user.foo = 'some value'
processUser(newUser, pageView)
} else { // user found by token
user.foo = 'some value'
processUser(user, pageView)
}
})
} else { // token does not exist
token = new Token('some value')
resp.setToken(token)
var newUser = new User('John Doe')
user.foo = 'some value'
processUser(newUser, pageView)
}
processUser(user, pageView) {
PageViewRepositiry.save(pageView, function(error, savedPageView){
if(error) {
throw 'error'
}
user.pageViews.push(savedPageView)
// save the modified savedUser
UserRepository.save(user , function(error, savedUser){
})
})
}
It uses Repository pattern as abstraction over database layer (same as the Repository pattern in Spring applications).
Basically it finds user by incoming token (from http req object). If user is found then updates user entity and adds the saved pageView entity and saves the modified user. If user is not found by token then it creates a new User, updates the user with saved pageView, saves the user.
How the same code will be written in Spring Project Reactor (Flux) ?
Is it possible to solve this problem without using block()? Ideally I would like a solution that does not use block().
First of all, you have some logic to generate a token if a token isn't present. For example:
private Mono<String> getToken(String token) {
return Mono
.just(token)
.switchIfEmpty(Mono.just("some token"));
}
In this case, it's a bit overkill to use switchIfEmpty for this, but I assume your process to generate a token is a bit more complex, otherwise you could have worked with Optional<String> in stead (eg. token.orElse("some token")).
Additionally, we also have some logic to either find the user by its token, or create a new user if there is no user by the given token:
private Mono<User> findUserByToken(String token) {
return userRepository
.findByToken(token)
.switchIfEmpty(userRepository.save(new User("John Doe", token)));
}
Now that we have these methods, we can create a PageView and use these methods along the way. The reason I start with creating a PageView is because that's the first "constant" in the entire token, regardless of whether there is a token/user found:
return Mono
.just(new PageView(uri))
.flatMap(pageViewRepository::save)
.flatMap(pageView -> getToken(token)
.flatMap(this::findUserByToken)
.doOnNext(user -> user.setFoo("foo"))
.doOnNext(user -> user.getPageView().add(pageView)))
.flatMap(userRepository::save)
.map(User::getToken);
Now, since you need the token to add to the response, and I figured out that the token is part of the User object somehow (otherwise UserRepository.findByToken() wouldn't work?), it would be easier to just use User::getToken at the end to retrieve the token to pass to the response.
Be aware though, the repository pattern does work properly with Spring, but there is only reactive support for MongoDB, Cassandra, Couchbase and Redis. Other than that there's also reactive support for PostgreSQL through rdbc, but I don't think Spring data has support for that.

Node.js and mongoose - prevent salt and password to return to client

I have a node.js app with mongoose. my problem is that when returning entities with populated user, the user data includes secure data like salt, tokens and password. I used the following method to prevent private data from going back to client:
User.methods.toJSON = function() { // Do not change to lambda expression
const SERVER_ONLY_PROPERTIES = ['tokens', 'salt', 'password'];
var user = this.toObject();
SERVER_ONLY_PROPERTIES.forEach(propKey => {delete user[propKey]});
return user;
}
Everything worked great, until I used the lean() function in my code.
when using lean the toJson method isn't being called and the private data returns to client. what are my options?
Instead of taking out the stuff that you don't want to return, you should instead have a process that builds a new object to return that explicitly includes only the necessary pieces of data. That's the best practice as far as security, if I'm not mistaken.

owin oauth webapi with a dynamic TokenEndpointPath

I've successfully implemented oAuth using OWIN in my WebApi 2 Server with:
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions {
TokenEndpointPath = new PathString("/api/TokenByPassword"),
// ...
});
However, I would like the TokenEndpointPath to be dynamic as I will have multiple databases each with their own account records.
I believe I want something like:
TokenEndpointPath = new PathString("/api/{databaseid}/TokenByPassword");
I don't believe OAuthAuthorizationServerOptions supports this and even if it did - how would I get the databaseid ?
I could implement this in my own WebAPI with AttributeRouting, but then what would be the correct OWIN calls to make in that WebAPI to generate the correct BearerToken?
I found the answer..
Even though the TokenEndpointPath is specified in the OAuthAuthorizationServerOptions, the OAuthAuthorizationServerProvider has a delegate called OnMatchEndpoint. Inside this delegate, you can access the Request.Uri.AbsolutePath of the call and if it matches your criteria, you can then call MatchesTokenEndpoint() in which case OnGrantResourceOwnerCredentials will get called where you again can gain access the the Request.Uri and pick out the {databaseid} and use the correct database to Grant access.
OWIN is very flexible, but not immediately obvious which calls to make when to do what you want when it is something not quite straightforward.
Just to make it clearer, here is the implementation of the function MatchEndpoint of the class that extend OAuthAuthorizationServerProvider, as suggested by David Snipp :
private const string MatchTokenUrlPattern = #"^\/([\d\w]{5})\/token\/?$";
public override async Task MatchEndpoint(OAuthMatchEndpointContext context)
{
var url = context.Request.Uri.AbsolutePath;
if (!string.IsNullOrEmpty(url) && url.Contains("token"))
{
var regexMatch = new Regex(MatchTokenUrlPattern).Match(url);
if (regexMatch.Success)
{
context.MatchesTokenEndpoint();
return;
}
}
await base.MatchEndpoint(context);
}
Be careful on what you do in there because it is called at every request.

Resources