Expose api in monolithyc Jhipster APP with OAUTH2 base Security - jhipster

Can anybody help me?
I built a Jhipster monolithyc app using Security based on Keycloak. This keycloak access to my corporative ldap and all works perfect. When somebody wants a page it redirects to http://localhost:8080/login and it redirect to keycloak to sing in, it returns to http://localhost:8080/login and it gets the token of the login user, so the user can access base on his role-user permissions.
Now, we want to expose the api to third party companies so as to reuse the bussiness logic of my app. (we can do it with web services but we want to expose our restful api). They have their own applications (desktop, web, etc) and we want to expose our api so they can communicate with us with the same securicy policies. they have users in our ldap. can anybody tell me which is the best way to expose it with user-role permissions.
One way is that they can send us their login information (user, password). We know it is not the best way , but we dont know how to do it other way. Does anybody know how to login with keycloak based on this user login. We enabled direct conecction and we are able to get the Keycloak access token with password flow. But, if we do this way, how can we convert this token in a OAuth2Authentication object so we can generate JSESSIONID to make the calls to the api?
We disabled csrf to make this possible.
Any ideas?
Thanks in advance

After a few days research, I reached a solution.
Here is the code:
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Bean("resourceServerRequestMatcher")
public RequestMatcher resources() {
return new AntPathRequestMatcher("/external-access/**");
}
#Override
public void configure(final HttpSecurity http) throws Exception {
http
.requestMatcher(resources()).authorizeRequests()
.anyRequest().authenticated();
}
}
This way I have both WebSecurity based on Keycloak and password flow base Resource. For this solution, the api I want to expose has both /api /external-api mappings, first for web navigation and the other for direct access. To access via the second way you have to call first keycloak to get a token and then access /external-api with that token.
Perhaps there is a better solution (client credentials), but i need the login user to resuse my endpoints.

Related

IdP as the master session

Background
I'm trying implement a browser-based login for a native mobile app from an existing Single Page Application. It uses WebView to render the SPA and it uses Keycloak OIDC as its Identity Provider.
The SPA and IdP is located in completely different domain and authentication is done by redirecting to the SPA domain after a successful login and retrieving the active session (cookie) from IdP domain in one of the SPA's server. The authentication check is achieved by using keycloak middleware which I believe is the protect.js
Summary:
Perform Login -> auth.idp.com
Redirect -> best.app.com
Is Login? -> best.app.com/login
Does auth.idp.com session exists?
User is logged in, redirect -> best.app.com
Token is passed in the URL and is stored only in memory
Token is used to establish WebSocket connection
Issue
Based from the spec, the authorization should happen in the browser / in-app browser, and authorization code must be passed via custom URL scheme. Having that in mind, the SPA that resides in the WebView of native mobile app will never establish a session from IdP's domain since this will be delegated from the browser which is on a different process and obviously using a different cookie store than on WebView in the mobile app, which makes our existing solution to break because it is relying on the IdP's domain cookie.
Proposed Solution
The issue I described above can be mitigated by cutting the reliance on IdP's session and by managing the SPA's own session, which basically means storing the token persistently that can be obtained from the IdP (which the current solution doesn't do).
(I don't want to detail much of the solution since I just want to focus first on the concept of storing the token. I think it's better for me to put this in a separate discussion if someone is interested)
Opinion
It seems like the current implementation doesn't really follow the best practice for OIDC flow but somehow, Keycloak has made some middleware to remove the need to use these tokens (authorization code, id token, and access token)
Relying on IdP's session when implementing SPA or non-web apps seems like not an option, because there is no way to obtain the cookie without reloading the page and provided that IdP session exists in the same cookie store as the SPA.
Redirecting to the IdP's session is not a good user experience for SPA. See the same sentiment here but it seems it does not have any answer: https://lists.jboss.org/pipermail/keycloak-user/2016-October/007937.html
Question
With regards to my proposed solution, i.e., storing the token retrieved from IdP, is there any security flaw or something non-industry standard it's going to introduce? If so, what are those?
Is it typical for OIDC flow to rely on IdP's session (cookie) to check if user is logged in or not?
If answer from #2 is NO, is that authentication flow specific for Keycloak only or does it exists for other IdP as well?
If answer from #2 is YES, is it common for IAM solution to programmatically check if the IdP domain contains a valid session (cookie)?
Is the current implementation flawed knowing we are aiming for SPA?
How does Keycloak handle sessions?
If you're using the default Keycloak middleware in your server and use keycloak.protect() for protecting endpoints, it checks on the request.session['keycloak-token'] which contains the access_token that was created during the token request after user login. If this exist and valid, it means user will not be redirected to Keycloak login page.
How does Keycloak create sessions?
Providing username and password which can be done manually using Keycloak's login page.
Cookies - if you pass valid cookies that are recognized by Keycloak, i.e., KEYCLOAK_SESSION, KEYCLOAK_SESSION_LEGACY, ..., a session will automatically be created.
How to access protected resources?
When using the keycloak-connect client adapters, you can access protected resources if the user agent (browser/app), has a valid session in your server OR if the request contains valid Authorization header.
Standard Solution
Access protected resource via Authorization header and use access_token which the keycloak.protect() also accepts. You can obtain this token in a standard way using Chrome Custom Tabs for Android and ASWebAuthenticationSession for iOS. You can also use AppAuth (iOS, Android) to lessen your work.
Store the refresh_token and access_token from native mobile and inject this in the HTTP request of WebView if possible.
Have a way to check for access_token validity and use refresh_token to request for a new one. If requesting for a new one fails, i.e., the authorization server verifies it's not valid anymore, that means users would need to re login again.
By using the standard solution I have proposed above, you should not need to create a band-aid solution for your issue. Hope this helps anyone that have faced similar issue.

SPA + API OAuth flow, what to use?

We are struggling about what OAuth flow to use with our app.
We are using Node.JS as our back-end API and Angular as our front-end.
What we want to do is, log in an user, retrieve an access token and use this access token in order to make some API requests (basic POST/GET/PUT/DELETE).
A user (still unknown at this point) lands on a login form OR a register form. He proceeds to the login or the registration.
Once logged he's on his dashboard with an access token, now every time he wants to interact with the API he must use his access token in order to interoperate with the back-end. (which is a classical behavior).
This seems easy, we wanted to use the Implicit Flow but we need a client_id in order to retrieve an access token and the user is still unknown at this point.
We then thought about using the Password Grant flow because our users will have a login/password, but OAuth specs. recommend not to use it except we have no choice.
I know this is a super basic question but what kind of OAuth flow do you recommend with this ? If we have no choice we'll just use the Password Grant but wanted to explore every single solution.
Thanks !
I'm not sure I understand what you mean by:
we wanted to use the Implicit Flow but we need a
client_id in order to retrieve an access token and the user is still
unknown at this point.
If you are using Oauth2.0s implicit flow then your angular app should be registered as a public client with the authorisation server - that process would give you a unique client_id for your angular app. Your angular app can then use the implicit grant and redirect the unknown user to the authorisation server's authorise endpoint passing along in the querystring its client_id along with its redirect_uri and various other things.
The authorise endpoint will prompt the user to register/login to the identity provider and consent to the scopes your Angular app requests.
Once the user logs in (or registers), the authorisation server should then redirect back to your Angular app's registered redirect_uri passing an access_token in the hash-segment of the returned http querystring.
Sorry, I know that I'm not answering directly to your question.
But did you consider using an authentification backend as Auth0 ?
Security is key and OAuth is a complex protocol.
Auth0 give you every thing you need to manage users, use a social identity provider, and integration with Angular.

Native app OAuth2 authorization

we want to create a native mobile app using OAuth2.
How to protect from stealing clientID (this information can be obtained by anybody)? Someone can create his own app and act as our app by using our clientID?
Yes, if someone retrieves your clientId/clientSecret, he can act as your app and sadly, there is no way to fully remove credentials from your application.
At a higher level, your app needs an identifier and a secret to authenticate to your service. If you remove the secret from your app, you need to get it from somewhere else (it could be your user typing it, this would be the same as having an auth for the user and giving him a token to perform further API calls).
However, you can make it harder for reversers to obtain the credentials, as explained in this article.
To make it even harder, you could force all your API calls to be done in HTTPS and enable SSL Certificate Pinning thus making Proxy Debugging/Man In The Middle difficult to pull off.
Ultimately, you should clearly identify which API calls should be public (with only the OAuth token to access those resources) and which should require a user authentication.
PS: Google's (Android Security Best Practices)[https://developer.android.com/training/best-security.html] could be a good start !

Login App with IdentityServer4

I have to develop a SSO system and I have to do it using IdentityServer4. I have gone through the documentation and examples but I have some doubts. To be honest I don't quite get it, but I am really new in Oauth2 and OpenId Connect.
We will have a bunch of clients (web apps), each of one of those will have their own Web APi. And we have to have a centraliced Login App for all of those. I think the example with the javascript client is the closes to the thing we want to achieve. Also, a user might have permission to access one client (app), but not another, so the IdentityServer must provide information about wich clients (apps), that particularly user can access.
So, These are the things I don Understand:
1.- In the documentation I can read there are two tokens, an Identity Token and Access token. But in the examples all I see are the access tokens. It seems to me that the access token is the one with all de info needed. am I wrong?
2.- Also, I have read about de Grant Types and I'am not quite sure wich one we must use. At first I thought to use the ResourceOwner password, because it requires the client, the secret, a user and a password, wich I assumed it could be the end user. I found this example http://sunilrav.com/post/How-to-Customize-Authentication-in-Identity-Server-4 were one could customise the class that validate the user and password. I thought that this could be the way to go but the documentation statesa about this grant type "...This is so called “non-interactive” authentication and is generally not recommended.". The javascript client example uses the implicit Grat type, wich the documentation states is for browser-based applications (our client apps will all be browser based using react).
3.- can my Login app be a Javascript (react) app? The example Quickstart is made in MVC.NET. This login app connects directly to de IS4 server without asking for a access token? (In the example the app is embebed in the IS4).
4.- Can I protect with IS4 a WEB API which is developed in .net framework (4.6.2) and not in .Net Core? I havent Found Any examples.
the documentatios I followed is the offcial. The examples (quickstart) are also there. (I can't post more than two links).
thank you very much for reading and for your help.
Identity Token and Access token
Identity token is the one that contains the identity of the user, that will tell the client app that what user it is. After successful login, user will be redirected to the client app with these tokens. Response will also have claims, such as permission scopes, name , email you can add custom claims as well.
Access token is used to access your protected web api resource. You have to send the access token with each request to access the api.
Grant Types
Grant types is basically how you want your client app to interact with the auth server. https://identityserver4.readthedocs.io/en/release/topics/grant_types.html
can my Login app be a Javascript (react) app? Your client app can be a javascript app but your auth server that is the identity server which will have the login/signup pages(and other login jazz) and account controllers should be you MVC app. As, everything is already done using MVC and Entity framework, why you want to re do everything.
Can I protect with IS4 a WEB API I am not sure about this one, but I dont see why you would not be able to do it.
This is a good answer for basic IdSrv flow!
UPDATE In my understanding, the answer to which Grant Type to use it depends on your client application requirement. If you want to use a Javascript client you can use Implicit Flow, but you won't be able to use refresh tokens and your access token is not 100% secured with the browser as client can access it.
If you want to open your web api to public then you can use client credentials flow. If you want to be more secure you should use Hybrid flow or HybridClient credential flow. ( again depends on the requirements ). with this you will be able to use refresh tokens and in this way your access token would be more secure.

Implemeting Authentication using OpenId Connect implementation for Azure AD?

I am trying to implement Authentication in our website using the Azure AD, following the below reference. Our website uses the below stack ASP.NET, MVC5 hosted on IIS. basically use OpenId Connect protocol for website authentication and use oAuth2.0 protocol for delegated access to use the token for Authorization.
https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet
Getting token from the Azure AD logic is there in the Startup.Auth.cs class, which is invoked from the OwinStartup class.
When I implement this in our site, Startup.Auth.cs ConfigureAuth is executed only once during the APP start and as per the above reference.
Decorating the controller classes with the [Authorize] or adding the SignIn() with check if the request is authenticated or not and call the Authenticate code again.
public void SignIn()
{
// Send an OpenID Connect sign-in request.
if (!Request.IsAuthenticated)
{
HttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/" }, OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
}
The issue is that The SignIn() method is not getting in our application and also curious on what the [Authorize] attributes does?
I highly appreciate any insight on these. Thanks much in advance.
ACS does not support OpenId Connect and is no longer being developed - hence the first part of the answer would be - what you are trying to do is not supported.
That said, are you certain you are referring to ACS? That sample refers to Azure AD, which is a different offering.
For the rest of the answer I will assume that you do refer to Azure AD.
From your description I am not understand what is the problem you are experiencing. ConfigureAuth only needs to be executed once to do its job, which is adding to the request processing pipeline the modules (middleware) responsible for handling authentication. I am not sure to what code you are referring to with "Authenticate". There should be no such call here - when you request a route decorated with [authorize], ASP.NET will enforce that the caller is authenticated; if it isn't, as it is the case for the first request, this causes the opened connect middleware to generate a sign in request. The Signin() method does pretty much the same the same, but without having to attempt access to a resource marked with [authorize].
Don't use [Authorize] attribute with the controllers if you have explicit SignIn() action.
You might be messing up with authentication cookie and Session variable.
Check this link
for details.

Resources