REST best practice cloud - rest

I have a set of REST services on IBM cloud. Ingress is integrated with Appid for authentication. Ingress adds the token id & access id to the authorization header.
Now on the API side (springboot) do I need to validate the user again on every request ? will this be redundant ? If no, which appid api can be used to authorize the user. Any reference to similar example
Already gone through the example on IBM cloud site. One is about ingress & appid integration, but does not talk about REST services layer how to handle the authorization tokens there.
Another is only about spring and Appid, (does not talk about ingress)

Authentication versus Authorization is where the line is drawn. The Ingress integration with App ID does the authentication for you and your REST service (application) can be assured that the request if it comes through is authenticated. Now just because the user exists in your system and has provided the right credential does not mean that he is allowed to access the service he is trying to access or view the data he's trying to view which is where the authorization comes into play - the REST service can use the authorization tokens to figure out if the user has the right access to use the service.
Here's a good article that talks about the use of Roles - https://cloud.ibm.com/docs/services/appid?topic=appid-tutorial-roles

In any application - REST, UI or otherwise - multiple levels of security may be necessary depending on your requirements. Authentication verifies the user is who they claim to be, authorization checks what permissions the user might have. Each application might have its own rules for what the user can access.
In your case, you have authenticated the user facilitated via Ingress with AppID, which supplies a user principal (identity) to your application. However, should every user have access to all of your application endpoints? If the answer is no, then you will need an authorization model, for which a common approach is RBAC (role-based access control).
Even without an RBAC requirement, it is still wise the validate the user's principal in some form for each request. For example, perhaps the user belongs to a domain that you might not expect, or should no longer have access to this specific REST application. Your application server may have features that assist you with a simple authorization feature, or you can custom build your own validation.
At present, as the identity provider, AppID can be the store of the user's role for RBAC. However your application or application server must decide what to do with that role.
If you are looking for a Cloud-centric authorization solution, you may want to consider exploring Istio's authorization policies:
https://istio.io/docs/concepts/security/#authorization-policy
https://cloud.ibm.com/docs/containers?topic=containers-istio

Related

How to perform user registration and authentication between a single page application and a REST API with OpenID Connect

Consider that we have:
An SPA or a statically generated JAMStack website.
A REST API.
The website is being served with nignx that also reverse proxies to our API.
--
It is required that a user should be able to register/authenticate with an identity provider (say, Google) through the OpenID Connect protocol. For the sake of simplicity, let us assume that the user has already registered with our API.
Talking about authentication using OIDC, from what I have read on the subject, the steps you take are the following:
Register the application with the IdP and receive a client id and a secret.
When the user initiates a login (with Google) request on the API ('/api/loginWithGoogle') the API sets a state variable on the request session (to prevent CSRF) and redirects the user-agent to the IdP's login page.
At this page, the user enters their credentials and if they are correct, the IdP redirects the user to the callback URL on the API callback (/api/callback).
The request received on the callback has the state parameter (which we should verify with the one we set on the session previously) and a code parameter. We exchange the code for the identity token with the authorization server/IdP (we also receive access/refresh tokens from the auth server, which we discard for now because we do not want to access any APIs on the behalf of the user).
The identity token is parsed to verify user identity against our database (maybe an email).
Assume that the identity is verified.
-- The next part is what's giving me trouble --
The documentation that I have read advises that from here we redirect the user to a URL (e.g. the profile page)and start a login session between the user agent and the API. This is fine for this specific architecture (with both the SPA/static-site being hosted on the same domain).
But how does it scale?
Say I want to move from a session based flow to a JWT based flow (for authenticating to my API).
What if a mobile application comes into the picture? How can it leverage a similar SSO functionality from my API?
NOTE: I have read a little on the PKCE mechanism for SPAs (I assume it works for JAMStack as well) and native mobile apps, but from what I gather, it is an authorization mechanism that assumes that there is no back-end in place. I can not reconcile PKCE in an authentication context when an API is involved.
Usually this is done via the following components. By separating these concerns you can ensure that flows work well for all of your apps and APIs.
BACKEND FOR FRONTEND
This is a utility API to keep tokens for the SPA out of the browser and to supply the client secret to the token service.
WEB HOST
This serves unsecured static content for the SPA. It is possible to use the BFF to do this, though a separated component allows you to serve content via a content delivery network, which some companies prefer.
TOKEN SERVICE
This does the issuing of tokens for your apps and APIs. You could use Google initially, though a more complete solution is to use your own Authorization Server (AS). This is because you will not be able to control the contents of Google access tokens when authorizating in your own APIs.
SPA CLIENT
This interacts with the Backend for Frontend during OAuth and API calls. Cookies are sent from the browser and the backend forwards tokens to APIs.
MOBILE CLIENT
This interacts with the token service and uses tokens to call APIs directly, without using a Backend for Frontend.
BUSINESS APIs
These only ever receive JWT access tokens and do not deal with any cookie concerns. APIs can be hosted in any domain.
SCALING
In order for cookies to work properly, a separate instance of the Backend for Frontend must be deployed for each SPA, where each instance runs on the same parent domain as the SPA's web origin.
UPDATE - AS REQUESTED
The backend for frontend can be either a traditional web backend or an API. In the latter case CORS is used.
See this code example for an API driven approach. Any Authorization Server can be used as the token service. Following the tutorial may help you to see how the components fit together. SPA security is a difficult topic though.

Exposing Cognito Protected AWSGateway APIs to clients

Use-case:
We have a few AWSGateway APIs which our clients can use to do somethings in the backend. These APIs are Cognito protected. Currently our clients are using this APIS through an android app which was built using Cognito Mobile SDKs.
Now we are trying to expose these APIs to our clients to be integrated into their internal workflows.
I was trying to find what is the best way to do this. Currently I am not able to find any resources on how to do this.
I have seem the server side user of AWS Cognito but I don't think that is what we want to do here.
Thanks.
To answer your question correctly we need more information.
Can the internal workflows be configured to use REST Services?
What authentication processes does the internal workflows support?
SDK or no SDK
You can access the webservices in API Gateway via a generated SDK or your own code.
Instructions to generate an SDK from the API Gateway Console are found here.
To invoke the webservice with authentication can be done in four ways IAM, API Keys, Cognito, custom authoriser. I am going to mention the first three.
IAM
Step 1, create a user in IAM with an access key and secret key.
Step 2, is too setup a role to access the API using IAM. Go to
IAM, select roles, create a role, and grant it access to your
API Gateway functions. Which would look something like this:
Sample IAM Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::account-id:user/Alice",
"account-id"
]
},
"Action": "execute-api:Invoke",
"Resource": [
"arn:aws:execute-api:region:account-id:api-id/stage/GET/pets"
]
}
]
}
allocate this role to the user you created. Policy examples are available here.. For more authentication options that include local certificates etc look here.
Step 3, call the API using the AWS Secret and Key SDK.
API Keys
If you add keys to your APIs the mobile app will fail as it does not have these keys. It would be best to deploy a different version of your APIs that could wrap the existing ones, could provide additional functionality specific to the workflow. To find out how to do this follow this link.
The advantage of API keys are that you can throttle access to your API Gateway functions, remove the keys at will, recycle them etc.
Cognito - Federated Users
Your mobile users are actually authenticating using federated users. However, one of the federated user channels happens to be cognito. You can add more, OpenAuth, Google, Facebook, SAML, etc, here you could add the Authentication type used by your client. A user would then use their username and password, to authenticate to the clients security provider, those credentials are then passed through to the API via federated users, and therefore federated users must be setup to use the same authentication mechanism as your client. See the following blog post
For this solution we have multiple options. 1. Pass the user credentials through to the API with federated users, this assumes the users interface calls the webservice but as you mentioned it is workflow, and I assume the user does not access the service directly as they do with the mobile application. i.e. services are called by a machine as a background process on a server. Which means this solution will not work. Option 2. is to create a new user, in cognito for the client. This is the same as accessing the service via the mobile app. To do this needs a little work extra work on the client as you need to retrieve the temporary access tokens.
Step 1. Use the SDK, or code the interface to the API on your own.
Step 2. Generate a user in Cognito for the backend system to use.
Step 3. Use the cognito user to obtain access tokens
Step 4. Use the access tokens to access the webservice in API
gateway.
Suggested solution
Create a second version of your API as a wrapper or extension to your mobile API and use API Keys as described above. Why?
Can throttle access to the APIs
A different version means you can extend it and add additional functionality specific to workflow
Easiest to implement as there is no key exchange, such updates to
the request header.
EDIT: My suggestion of solution 2 is incorrect. AWS Documentation says the following To include API methods in a usage plan, you must configure individual API methods to require an API key. For user authentication and authorization, don't use API keys. Use an IAM role, a Lambda authorizer, or an Amazon Cognito user pool.
AWS Also says the following is available for controlled access
Resource policies let you create resource-based policies to allow or deny access to your APIs and methods from specified source IP
addresses or VPC endpoints.
Standard AWS IAM roles and policies offer flexible and robust access controls that can be applied to an entire API or individual
methods.
Cross-origin resource sharing (CORS) lets you control how your API responds to cross-domain resource requests.
Lambda authorizers are Lambda functions that control access to your API methods using bearer token authentication as well as
information described by headers, paths, query strings, stage
variables, or context variables request parameters.
Amazon Cognito user pools let you create customizable authentication and authorization solutions.
Client-side SSL certificates can be used to verify that HTTP requests to your backend system are from API Gateway.
Usage plans let you provide API keys to your customers — and then track and limit usage of your API stages and methods for each API
key.
Not all the approaches above are intended for authorisation, for example CORS actually protects the user from cross site scripting, and as seen API Keys are only for usage plans. Resource policies just further secure the API by limiting access to IP Addresses, thus your only options really are IAM Roles as described in option 1, and federated users as described in option 3 or your own custom lambda authorize, if you are using Lambda, or your own authorizer if you are using something other than lambda wrapped with API Gateway.
I guess it will be service to service or (Server to Server) communication, for this terminology used is Oauth Standard is client_credentials grant type.
Please refer the documentation for getting token
Once the token is acquired, you need to pass this token either Authorization or API Gateway Custom Header for AWS Cognito.
You can use API Tokens alone for authorization (unless this has been removed recently)
I have used them on multiple applications.
This is not recommended for Authentication -- but it is application specific if they are sufficient for authorization
They have been supplemented by more secure methods at the expense of significant complication for both client and server.
API Tokens have the advantage of ease of use for issuer, client and server as they do not require complex signing or protocols -- however they are not as fundamentally secure as they may be reused and generally do not expire as quickly. Otherwise they are equivalent to bearer tokens.
Security is very context dependant -- consider these question:
what exactly are you protecting against (providing security for) ? What is the risk and cost of a security breach ? What is the cost/effort to implement and use it?
Many security 'holes' are not in the authentication protocol handling itself but rather in how data is managed 'outside the box' -- No security is perfect, meaning aiming for perfect security has unbounded cost with decreasing effectiveness. Generally, it is recommended to balance the risk and cost of potential loss vs cost to implement and maintain.
You can have a 'highly secure' API but also have a high risk of breach and data loss due to handling before and after passing through the protected gateway. There are many reasonable cases where instead of focusing on securing the 'front door' with bank vaults and armoured trucks, instead securing the data handling such that no data that is a significant security risk passes through the front door.
AWS Provides a range of technical features -- but it is ultimately up to each customer to implement them appropriate for their use. API Keys do have a range of appropriate use cases, particularly in server-to-server communications, especially where personal identity (and PI data) is not involved, or where the API involves mainly services instead of data (e.g say a image thumbnail API that stores no state and provides no access to data). When backed by use of HTTPS/SSL and possibly other security factors such as account passphrases, IP range whitelists, and a general policy of least-access.
Don't underestimate the "Sticky Note" factor. If you make secure access too painful to your users they will find a way to make it less painful, but less secure then simpler measures which they would not have had an incentive to circumvent.

Authentication without user credentials

I'm putting together a personal React site and want to send requests to an AWS API Gateway. However, I just want my site to be able to pull data. There will be no user model and every auth model I've ever used requires the user to do something with sign-in, be it user/pwd or AD. Can someone guide me to a model that covers this scenario?
One common approach is to use a Cognito Identity Pool with "Unauthenticated Identities" enabled. You can secure your API gateway endpoints using IAM, and require requests to be sig4 signed.
With this approach, Cognito is used only in a kind identity broker capacity, not as an actual identity provider. You do not need to create a User Pool or use any other identity management features of Cognito. In this capacity, Cognito is essentially just a thin layer between your code and the underlying STS APIs that produce the IAM keys your application needs.
Using the Cognito SDK, you request temporary IAM credentials (access key, secret key, session token) that can be used to sign the requests.
This answer outlines one way to accomplish this. When the protected AWS resource you want to access is API Gateway, your code may look something like the example near the end of this post.
I typically either use aws-api-gateway-client, as the example does, or aws4 with axios to sign requests.
As noted in the linked to answer above, I normally use AWS.config.credentials.get(), rather than AWS.CognitoIdentity.getCredentialsForIdentity() to actually get the IAM keys (as in this doc).
The signed requests then include an Authorization header that is very difficult to counterfeit. I don't want to suggest that this approach is bulletproof, but it does at least give you a reasonable level of confidence that your API Gateway endpoints are only being successfully invoked by your application.

Role based authentication in Vue using JWT

I'm working on a project with a RESTful Java backend and a Vue SPA front-end. Whilst figuring out how to do user authentication I came across JWT-tokens and since it (sorta) was what I was looking for I recklessly implemented it.
Few weeks later I realize that because the content being shown on the client side, depends on the users role, the client of course needs to know the users role. For obvious reasons I don't want to store the users role inside my client.
My question: I could create a request on the server that looks at the Authentication header and returns the role, but would this be save? If not are there any common strategies when it comes to roles and JWT-tokens? Or should I forget the JWT way of doing things and implement another kind of authentication entirely?
JWT is the common way to Authenticate users with SPA as Frontend + REST Api as backend.
You definitely should not store your Token Secret in frontend app.
You definitely can do kind of /user/roles endpoint in your API which will return the list of user's role.
Point 2 solution is 100% safe. Why? Even if someone will hack your frontend app to show the content which they should not see, your backend is checking Authorization at endpoint, so they will not get/put/change any data which they have not privilege to access in their JWT.

OAuth Security with Pre-Configured Authorization

I have a scenario where a user has logged into to a web application (authenticated with OpenID Connect) and then needs to access data from a separate REST service.
The REST service needs to determine whether or not the user has permission to access the requested data, but if the user does have permission, then it should grant authorization to the web application without requiring the user to interact with the UI.
Essentially, what I need is a two-legged OAuth solution where the client/relying party is fully trusted but the user, who's already been authenticated, is not.
Going in, I assumed that OAuth could accommodate these requirements, but none of the grant types seem to match the requirements:
Authorization Code is the opposite of what I need, as the user is pretty much automatically trusted but the client is not, requiring that the user grant access to the client via a web form.
Client Credentials trusts the client (which is what I need) but does not give the service an opportunity to determine if the user has permission to the resource (user auth tokens are not passed to the service, making all requests essentially "anonymous").
ROPC (Resource Owner Password Credentials) would appear to be the only option, but requires the web application to know and possibly store the users' login credentials (which is untenable).
Is this a gap in OAuth? Or am I misunderstanding these grant types? If OAuth can't support this scenario, is there another widely adopted open standard that I've missed?
Of note: I only own/control the web application, while the customers (all of which are businesses) own/control both the authentication servers and the REST services. Therefore, a shared, non-proprietary standard is necessary so that our customers will know how to configure their services (IBM, Microsoft, whatever) and so that I'll know how to pass along any authentication tokens, etc.
I think this is possible using normal OAuth2 flows. You have your web application use the code authorization grant to get a token to call the API on behalf of the user.
Your web application makes the call to the API attaching the JWT token in the Authorization header. If the REST service determines the user does not have permission to access the resource, it returns a 401 Unauthorized HTTP response code.
Your web application handles the 401 response by going back to the authorization server and using the client credentials grant to get an access token to call the REST API on behalf of the client itself.
As both grants allow you to get a refresh token, you should be able to switch between access tokens easily.
If there is no trust relationship between the web application and the REST service, there's no way around using the Authorization Code grant since the user needs to be involved anyhow to allow the web application to make the call on behalf of the user.
If there is a trust relationship between web application and REST service you should be able to use the regular OpenID Connect flow to get an access token to the web application at login time that can also be used in calls towards the REST service.
You may pass on the user information as part of a JWT (i.e. a structured) access token that is signed by the web application itself or the OP; that would be OAuth 2.0 compliant. See https://www.rfc-editor.org/rfc/rfc6749#section-1.4 and May an OAuth 2.0 access token be a JWT?.