AWS Cognito combined with other Rest apis except api gateway - authorization

Cognito is a powerful tool yet it's so hard to utilize it .
Trying to implement my business logic I ended up in some dead ends and I need some help.
My client app is an admin panel where a new admin can register providing a company.
Now there are 2 applications (Contests, Reviews) based on these companies .
So from the adminPanel the admin can create events for both apps through 2 different rest apis
The concept is 1 admin is related to 1 or more companies.I have to map that relationship somehow with Cognito .
Because cognito does pretty much well authentication but not authorization.
In every request not only I have to validate the user by the access token but I also have to see if the user is authorized to do the action based on the company.
For example if a user want to create a Contest event for his company.
I will make a request to Contest Api and I have to authorize that the admin is related to this company
Company entities are used from both apis so I have to expose them in a new api called companies.(If any api wants information about companies it should call the get company/{id})
My consideration is that in order to authorize a user in my apis I have to:
1) validate the access_token .
2) communicate with Cognito to get user informations.
3) call companies api to check if user is authorized to execute actions for this campaign.
So I kind of feeling that it becomes too complex and I need 2 services to authenticate and authorize each request(cognito + company api).
Is there any other way to implement cognito authorization logic without having to use a second api ?
P.S I have already check cognito triggers but they don't cover my needs .For example pre token generation trigger can add claims but it will add them in identity_token not access_token .Also my claims has to be an array of company_ids that an admin is related but claims supports strings and numbers only

Related

How to authorize different roles on a .Net 5 OAuth API

I have an IdentityServer4 application, a client application and a .Net 5 API. I want the client application to be able to talk to my API on the users behalf with an access token. Some users should be able to do admin requests while others should only be able to do normal user tasks.
I believe I need to add two scopes for these, api.admin and api.normal.
First question is where would I add these scopes in identityserver? Does the client request both scopes and just gets back whatever IS decides is right for that user?
Secondly, how do I validate what scopes are in the access token on my API. Method 1 should only be used if the access token contains the api.admin scope for eg.
Thanks!
First, scopes are something you typically hard-code in your client and it does not "vary" between users. It main purpose is to indicate what the "client" application want to have access to, not the user.
So you only need only one scope like "api".
Then you have different roles or claims in the access-token that describe what the authenticated user have access to.
You then use the authorization middleware in the API to determine what the user actually have access to.
Like what the picture below shows:
There is no reason that different scopes could not be requested by the client based on the user interacting with the client or even environmental based criteria.
As some quick example, a USER that has Authenticated to a Client Application that determines the user is a "Preferred Customer" vs a visitor might be granted scope to allow reading "Preferred Content".
The client then requests a "preferredcontent" scope for the "Preferred Customer" and not for the visitor.
And of course the Authorization Server may reject the scopes requested for any reason.

How to handle user permissions in front-end with OAuth 2 in RestFul applications?

Imagine we have an application that is implemented based-on restFul and OAuth2, and also of course we've stored the user's roles and permissions in the back-end which is implemented by Java and spring boot. So I want to know how can we handle the permissions of users in the front-end. Indeed, there are some fields or columns that should be shown to the user who has specific permission or role but other users can see limited fields or columns.
What is the most efficient and sensible solution to this situation?
Should the front-end fetch available field or columns from the back-end?
Should the front-end has all of the information about user credentials to decide?
or is there any solution to do this?
Here is the most common solution, where all security is enforced by the API:
API responses omit fields / columns that the user is not authorized to access
UI can ask the API which fields / columns the user is authorized to access
UI hides elements based on this API metadata
It is common to have an endpoint such as this, which the UI can send an access token to in order to get the above metadata:
GET /api/userclaims/current

API - allow users access to only data they created

This is an API related question that applies to the APIs that I'm working on and would like to know the standard way of doing this.
say a user1 has created accounts so he can access it by
GET /accounts
but when he accesses transactions for a particular account
GET /accounts/acct1/transactions
how would this API know that the acct1 actually belongs to that user1 and is not the case where user2 is accessing user1's accounts.
This api is accessed via a Mobile app using Oauth 2.0 tokens. So while the access token control the access to API endpoints, how do we control access to only specific user's data at that endpoint. (using scopes?)
I've been looking at Spotify's apis and they seem to be doing this via v1/me end point.. Still reading...
I'm a noob at this and it looks to me that this should be documented somewhere in a standard manner in some RFC, but I couldn't find it and would appreciate direction
Can you provide more details on your use case? Why are you using OAuth?
It sounds like you need an authentication protocol - i.e. a protocol to let your server know who is accessing a particular API.
To quote the OAuth website:
OAuth 2.0 is not an authentication protocol
OAuth's main use-case is letting one application perform operations on behalf of a user of another application.
As an example, if your server wants to post a message on Facebook on behalf of a user, you will use OAuth to obtain a token from Facebook which lets you post messages on behalf of the user. Note that, in the most general case, your application does not know which user is represented by the token. Indeed, the user may not even be a (registered) user of your application - they only have to be a user of Facebook.
Practically speaking, you often can use the token you have to query Facebook for the identity of the user. So your server would extract the OAuth token from the request headers and use it to issue a query to Facebook's Graph API to obtain the user ID.
Note that the user is a Facebook user rather than a user of your app, so you will need to somehow map the Facebook user ID to your own users and permission system - i.e. check your database to ensure that the user has permissions to do what they asked to do.
This is the mechanism that is typically used when using OAuth like an authentication protocol (which, as quoted above, it is not).
I should add that if your app obtains an OAuth token and passes it to your server for the purposes of authentication, then this flow is not 100% secure, as discussed for example here, so make sure you do proper risk analysis for your case. In a nutshell, a determined attacker can theoretically impersonate your app and obtain tokens representing other users.

How to make available the identity of a user across multiple microservices?

So let's take the basic e-commerce microservices.
Identity and access . This microservice will take care of user accounts, roles
and authentication. The authentication method will be the based on the usual
token based flow (user enters username + pass and server returns a unique and
random token via cookie). This service can also be used to get the user profile.
Cart microservice. This microservice can be used to put products in a cart.
Check what products a cart has. Etc ...
Asuming that "Identity and access" microservice will be used for generating the random token as a result of a succesful authentication, and for linking this token to a user, how will this token be used to make the user's identity available to the cart microservice? For example, when a user will add a product to his cart, he will send along the authorization token and the cart microservice will have to identify the user based on that token.
Could a distributed database be an option? A database which has these tokens stored and links to user built, and to which all microservices have access?
Or should all microservices get the user's identity from a special identity and access API which will expose users based on the access token?
A distributed data base definitely conflicts with the following basic principle of micro services:
A micro service owns its data and exposes it via well defined interfaces.
No other micro service may access data owned by another micro service directly.
So one solution in this case would be to have a token micro services or the last solution you have described.

What are some recommended user signup / logged-in user MVC/OData and public-facing API data access strategies?

We're building a new application that will have a user signup and logged-in user area. Authenticated users will have access to our API.
I wanted to separate the user signup OData endpoint from the logged in/API-access OData endpoints.
For new-user signups, a separate in-network API works. However, public-facing, I'd like to know some proven architectural strategies.
I would bet that you could use FormsAuthentication to lock down access based on users and/or roles in your MVC application. OAuth could be used in conjunction to handoff the identifying info to your authentication/authorization routines.
Here is an article on using OData and FormsAuthentication.