I have a setup like this:
Back-end REST API application - Single Instance running in Cloud Server - Let's call it as A
Public Users` Mobile app & browser clients - Let's call them together as X
We already are using Keycloak for Identity and Access Management. As per the current setup,
X to A uses Password grant flow, that is – a client is created in Keycloak with Client-Type as Public for user management and auth of X to A.
Now, we have to introduce new layer of back-end app, that is,
Back-end REST API application - Multiple Instances running in On-prem Servers across different physical locations - Let's call them together as B.
Now, both B and X both are clients of A, [i.e. A serve both B and X].
Please clarify:
Should I create another type of client in the same realm for B, like below?
B to A: Client credentials grant flow i.e. I have to create another Client-Type as Confidential for B to A, to configure a service-account for each of the instances of B.
If yes, please guide me on how to configure both Auth flows in A i.e. A has to auth both B and X.
I feel like this one as a bad idea - Using the existing setup as it is, which is explained below.
As per the new business logic,
X logs-in the app (mobile/web app) using username and password and calls an API of A to generate a QR Code, which will contain the hash of the user's (X's) access token and some other info.
A stores both hash and access token of X in the database
B gets the hash of the access token used by X to access A, from the QR Code scanned by the user. B uses the hash to validate the authenticity of the QRCode, by calling an API of A
As mentioned in the above business logic, if needed, A can expose an API, where the above said user access token can be retrieved through a get request, by sending the hash as a request header param or query. This token can be further used by B for further API calls to A.
I think that the above idea is bad, because, we are not supposed to send the user access token over the internet, even if there is a SSL/TLS connection between B and A.
Can the Client-Type, Bearer-Only be used in this scenario between B and A? If yes, Please guide me on this.
As you are having both Public and On prem services as clients, I would suggest the following:
As you said, X as public client shall use Password grant
B should use Client Credentials mechanism to get itself authenticated with Keycloak. Keycloak will provide it the access token through ${kc.realm-url}/protocol/openid-connect/token endpoint. This access token can be sent to A.
"A" should also be a registered client with its own credentials.
When "A" receives request from X or B, it should use a mechanism called Token verification through Introspection endpoint where it will get the token verified by calling Keycloak.
Introspection endpoint expects access token, client id and client secret.
This way, A can be sure that the token received by it is indeed issued by Keycloak.
Related
Scenario
A-> 3rd Patry SMAL, domain-xyz.com
B-> My App-Backend (.net core REST API), domain-b.com
C-> My App-Frontend (react app), domain-c.com
when a user tries to login in C, redirected to A and after authentication, a token is issued by B, and the token is added in the URL to C, redirect is issued from B to C.
It shows up the URL in C like domain-c.com/user_access_token, and this token is used to consume APIs from B.
Problem:
A visible token in URL is a concern, reported by security testers
Question:
how to change it to make this model secure?
please suggest, Thanks!
The flow which you are talking about is called implicit grant flow where you directly get the token in your front-end. In your case response type will be token.
Now the question is how to make it more secure. I suggest that instead of response type as token you should make it response type code.
This will give you a authorization code on the front-end (instead of access_token) which will be useless for hacker who's trying to steal your token.
Now this code is received at C and you send it to your backend B.
Do a authorization call to A now with client_id, client_secret and received code to get the access token. Using this access token create a session for the user.
For more information refer: https://developer.okta.com/blog/2018/04/10/oauth-authorization-code-grant-type#the-authorization-code-flow
We're planning integration between two services: A and B.
The service A is going to be an OpenID Provider, the service B relies on it to log users in and create new accounts.
The service A also provides access to its resources via REST API using OAuth authorization, the service B uses the OAuth Access Token obtained via OpenID Authorization Code Flow.
However, there are some cases when A wants to get data from B. There is an established agreement between these services, that A can access any data from B in the scope of a user that was created via OpenID Connect.
How could I design authorization for the service B API? What could A provide to B in an HTTP request?
I'm considering things like a classic API Key, but it doesn't look natural in this workflow.
There are no direct solution to your mentioned scenario from OAuth and OpenID Connect protocol perspective.
But from what you have explained, you have OAuth 2.0 access token protected services in service A. Also, A acts as an identity provider (with OpenID Connect support). If this the case, I believe you control token issuing process and validations.
One options is to enable services from B , which are protected from OAuth 2.0 access tokens. Which is similar to what you already have in A. And to consume those services, you will have some service/client implementations bound to A. What they would do is obtain tokens from A itself to communicate with B. This can follow client credential grant from OAuth 2.0 as there is no end user involvement (scenario involve service to service interaction).
This suggested solution is similar to API key usage but with added benefit of OAuth 2.0 protocol.This allows you to generate Access tokens with limited life time and allow refreshing them if required. Also, in case you want B's services to be consumed by another client, then things are straightforward.
My project include a web application, a mobile app and a REST API module.
The mobile app is made with Ionic 3 for android and uses a REST API located to an address like example.com/api.php on a server with https. The API has access to a MySQL database.
For the users who access the API I have to create the login/access to API function/logout since they already have the accounts created in the web application.
The main concern is to implement a secure login. Meaning, if someone tries to access my API without authorization (knows the address, the functions name or the used parameters name) to recive an error message. In order to access the API you must be logged in and to have the right to acces a certain section (I have multiple levels of access).
But how can I detect if an user that access my REST API is logged in and has the proper rights?
The plan:
For the login step
In order to access the REST API I have to login with username/password in app. I check if the credentials are correct (if the user exists then I determine the access level) and return a JWT with the user ID and other parameters if necessary (a token). Store in phones local storage the JWT.
To secure the access to REST API functions
The question is: HOW DO I DO THAT? How do I access secure a function from my REST API?
for every request that I make to the REST API should I send also the token from the Local Storage and verify it on the server side?
how do I perform the validation on the server? Do I store the token on the device and also on the server and compare them for each request?
Thanks a lot!
There are multiple ways to do it, it's all depends on you. Hence i am sharing the method i generally use, but not claiming it is most secure way.
We use encryption, decryption with private key. for example:
Register User Web-Service
ex. we have 4 params 1. username 2. name 3. email 4. password. with my register web service.
We will create SHA256 Hash using data concat with private key. then we will pass the hash key to server and at server side we will generate hash key with same method and compare both.
ex. string with private key = usernamenameemailpasswordprivatekey
sha256 of string = 7814b2d22af647308884acff0be4c675b7f72ba000cf1e8390520100cc930e74
You may have any sequence of your data string and same method will work with your server. Always use SSL certificate with your server for more security.
I am in the process of implementing IdentityServer3 in our company but I have hit a blank around how to handle client to client authorization and would appreciate any pointer in the right direction.
This is a summary of our requirements:
We have multiple web site clients that our users access. These are configured using the AuthorizationCode flow. Lets call these WebSiteClientA, WebSiteClientB.
We have multiple WebAPI clients as back end services that could be accessed by either a client (WebSiteClientA, WebSiteClientB) or a user (who has access to WebSiteClientA or WebSiteClientB). Lets call this WebAPIClientA.
Note: Our company owns the users identity as well as all clients.
Initially I though we could configure WebAPIClientA using the ClientCredentials flow. Then WebSiteClientA \ WebSiteClientB would be configured with the client credentials for WebAPIClientA and could generate an access token when it required access to WebAPIClientA, or alternatively generate an access token with limited scopes and hand this access token to the user so the user can access WebAPIClientA directly from the client side.
This would meet almost all our our requirements except 1 big one, we also want to be able to manage what scopes a client has access to for another client and with the approach of using the ClientCredentials flow anyone with the client credentials would be able to generate access tokens for all scopes under that client. ie WebSiteClientA should be able to generate an access token for WebAPIClientA with read & write scopes but WebSiteClientB should only be able to generate an access token for WebAPIClientA with the read scope.
In my mind the client\identity server conversation would be:
WebSiteClientA makes a request to the identity server for an access token to WebAPIClientA for scope X and provides the client secret for WebSiteClientA. The identity server then says yes, you are WebSiteClientA and we can see from our records you have access to WebAPIClientA with scope X, here is an access token.
Is this possible or am I looking at this in the completely wrong way and there is maybe a better approach to meeting the requirements?
It sounds like you're talking about two things.
The first is that in the APIs you need the user's id. To obtain the user id you have a decision if you want to build a trusted subsystem, or if you don't want a trusted subsystem (in the sense that your APIs trust or don't trust the MVC client to pass along the user's identifier). If you do a trusted subsystem, then the client credentials flow from the MVC client to the API is fine. If you don't want a trusted subsystem, then you need the MVC client to obtain an access token for the user (via implicit or hybrid flow).
The second issue you're asking about is if you can control the scopes each client is allowed to request, and you can via the AllowedScopes configuration property (or whatever it's called) on the client configuration. This setting is orthogonal to the first issue mentioned above.
In our scenario we have an on-premise device (A) making a call to our cloud hosted service (B). Each device belongs to a customer and each customer has a unique api-key and api-secret. These are securely held on the device.
The device uses these to authenticate via Client Credentials flow; token lasts for around 10 hours.
service B dumps the request onto a message queue.
service C takes from the queue, performs some processing and calls service D, service D calls service E.... etc.
Each service is a distinct physical boundary (think microservices) called by https.
We are using a "delegated authority" concept so that the token is passed around as a custom claim that can then be used to attach to the next request in the chain. This means each service is operating under the original device A requested authentication and has access to the custom, customer specific, claims created when device A authenticated.
We also pass the JWT token in the message as a string between service B and C and this works fine when we use it to set the bearer token in service C when it calls service D.
My problem is what if service B doesn't process the message within 10 hours (e.g. a fault). After 10 hours the token will have expired, and service B does not have access to the credentials used by device A to re-request the token.
I thought I needed a refresh token too, but this isn't supported for Client Credentials flow. Then I thought of "cheating" and making my token last "a very long time", but then I'm not sure how I can invalidate it in a security breach. My final option is to actually pass the api-key and api-secret in the token as a claim that can then be used to re-request a new token by any service in the chain... but this feels like a security breach waiting to happen. To be honest though, so does having the refresh token as it acts like a master password anyway.
Is there any advice / best practice on this scenario?
Many thanks
I see two options
a) make the token long lasting - but use reference tokens. This way you can revoke the token if needed
b) implement a custom grant that allows authorized clients to request a token copy with a new lifetime.