Identity Server Resource Owner flow with external Identity Provider - identityserver3

We have a project where the client requests the use of their own Identity Provider, in this case, it is SalesForce.
We secure the application using IdentityServer 3 and have configured it that for this client (based on parameters) it will use SalesForce as the IDP.
For the web app, no problem, Identity Server redirects to the Sales Force login page and everything works great.
Now we have a mobile app to build and the client would like to avoid having a web login page and would rather have a nice polished login form built in the application. This means that we will have to use the Resource Owner flow.
Now, the users creds are on SalesForce side so how does that work and is this at all possible in IdentityServer 3 ?
I see 2 possibilities but I kind of like neither of them:
Send the auth call to IdentityServer which should detect that it is up to SalesForce to validate the user and forwards the request there. I think it is not good as I would rather avoid having my IdentityServer dealing with credentials that he should not even know
Send a first auth call to SalesForce to get some "id token" that would then allow me to send another auth call to IdentityServer which will then recognize the "id token" and release an access token.
That seems like a stretch and forces the app to know that there is an IDP which is none of its business.
Any idea?

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.

How can I integrate with a third-party API secured with oAuth2 in asp.net core 3.1?

We're trying to integrate with an external third-party REST-API that's secured with oAuth2 but the service isn't really an identity provider, so I'm not sure what terminology I'm looking for. Obviously when it comes to looking at "asp.net core" and "oauth", millions of hits come up related to adding it as an identity provider but I don't think that's what we want.
This is how I would expect it to work, based on what I've seen in other saas apps:
User logs into the site
User looks at some "third-party integrations" page and clicks to add this one
User's browser is directed to the other service to login
On successful login, user is directed back and we have access to the bearer + refresh token which we store(?) and use.
Some use of this API is in response to user action (refresh to get results), but some is also just background work so I assume we're storing this information and using implicit flow to refresh the token for as long as we can unless it's revoked.
What asp.net core terminology am I looking for, how would someone properly describe this flow in oAuth terms? We're getting confused between authorization, authentication, providers, handlers, middleware, etc.
In terms of this third-party API oauth flow, in case people want to know, here's what's required:
We call a specific endpoint that tells us the correct authorization and token endpoints
We then redirect to the authorization endpoint, which presents the user with the remote service's login page.
The user logs into the other service and is redirected back and the code and grant_type=authorization_code are provided via the url
We call the token endpoint with that information to get the final bearer+refresh token

How to protect bearer tokens in a web app

I am trying to implement the Authorization Code flow described in RFC 6749 (OAuth 2.0) for a JavaScript-based application. I understand that I should use a web server back-end as a confidential client so that it can protect the access token and refresh token returned by the authorization server and not pass them on to the JavaScript front-end. Then all requests from the front-end to any protected resources go via the web server back-end, which attaches the access token to the request and proxies it on.
My question is how do I let the JavaScript front-end make use of these tokens in a secure way? I assume that I have to do something like set up a session on the web server and pass back a cookie that identifies the session. But this means that the JavaScript application then has a cookie that gives them the same privileges as if they just had direct access to the bearer tokens stored in the web server. How does having a web server to hold the tokens give extra security?
I understand that I should use a web server back-end as a confidential client so that it can protect the access token and refresh token returned by the authorization server and not pass them on to the JavaScript front-end.
No, it is a misunderstanding of the OAuth2 flows and goals.
Here is the OAuth2 main goal: your application (which can for instance be a JavaScript program running in the browser, a web server, both, etc.) MUST NOT need to know the user's credentials (most of the time a login/password pair) to access the service on behalf of the user.
Here is the way OAuth2 must be used to achieve this goal:
according to your needs, that is having a Javascript-based application running in the browser (i.e. not a node.js application), you need to use the OAuth2 implicit flow, not the authorization code flow. But of course, because your application is running in the browser, it will not be able to persist the credentials to access the resource offered by the service provider. The user will have to authenticate to the service provider for each new session on your application.
when your application needs to access the service provider when the user is not logged in, or when your application is able to persist credentials (because your application has its own credential system to identify its users), your application does not only rely on a JavaScript program running in the browser. It may rely only on a web server, or on both a web server and a JavaScript program that talks to this server. So, in those cases, you must use the authorization code flow.
So, as a conclusion, you have decided to add a web server to your application because you thought you had to use the authorization code flow. But in your case, you probably do not have to use this code flow, therefore you should select the appropriate code flow for your application: implicit code flow. And this way, you do not have to add a web server to run your application.
How does having a web server to hold the tokens give extra security?
This does not give extra security. Having a web server to hold the tokens is simply a way to let your application access the service on behalf of the user, in the background, when the user is not logged on your application.
While I agree with Alexandre Fenyo's comments, I just want to add the 2021 version. You should no longer be using the implicit flow as this is no longer considered secure.
For scenarios such as this where a JavaScript application has to handle tokens I would suggest using the Authorization Code flow with PKCE instead: https://auth0.com/docs/flows/authorization-code-flow-with-proof-key-for-code-exchange-pkce

Browser based OAuth / OpenID with persistent login

We have a regular web application with cookie based auth and now we want to split frontend and backend (api) in order to have third-party public API. So our backend will be on one domain and frontend on another one.
For authorization we would like to switch for OAuth 2 with JWT. In this case our frontend app will have to use access_token instead of cookie session and it brings a big old question:
How To Remain Logged In - The Infamous "Remember Me" Checkbox (part II from Form based authentication for websites)
From OAuth2 point of view our frontend application going to use something between Resource Owner Password Credentials Grant and Implicit Grant. It is closer to Password Credentials Grant since we still going to use usual login form and won't redirect user to another domain in order to sign in. At the same time it is closer to Implicit Grant since it's all going to be browser-only & JavaScript based when access_token will be saved in browser.
The RFC says the authorization server MUST NOT issue a refresh token if you use Implicit Grant and my question is if it's still valid in this use case when you don't really use a 3-d party OAuth but your own api? Instinctively I feel that having refresh_token in browser is a security hole and would like to confirm it with you guys, but that refresh_token seems to be the only way to have persistent login working the same way as we had with cookies.
**UPD** after #FlorentMorselli comment:
The OpenID specs still do not answer my question if I can use refresh_token with browser only application
Google says they provide refresh_token only for access_type=offline
OpenID Connect Core says you cannot use Refresh Token with Implicit Flow
OpenID Connect Core says nothing about using refresh_token with Hybrid Flow
There's only one place where it says something promising about refresh_token with Hybrid Flow, but nothing precise
UPD2 thanks to #reallifelolcat
It looks like OpenID Connect does not explicitly support Resource Owner Password Credentials Grant, meaning you have to redirect user to OpenID Connect server to perform login. Do you know if there is another way to authenticate with user credentials over OAuth 2.0?
I believe splitting api and frontend is getting more common these days and I'd appreciate it if you share how you solve this Persistent Login issue and if you drop it completely and force user to re-login every X weeks.
Thanks!
Access tokens and refresh tokens have nothing to do with login with OpenID Connect. These are only for authorizing access to user profile information and for perhaps authenticated service calls to your public API after the fact of login. Refer to the spec for the difference between the ID Token and the Access Token.
If you are going to use OpenID Connect for login, then from what you've wrote so far, it sounds like you need to host your own OpenID Provider (OP) since you want to avoid going to another domain to sign in:
we still going to use usual login form and won't redirect user to another domain in order to sign in.
If you want to be your own Identity Provider, then more power to you. This means that you going to have to deploy your own working instance of an OpenID Connect server, complete with authorization and token endpoints.
Now this is the part where your persistent login comes in. Your browser webapp will be a relying party to the OP server you now have. When a user tries to login to your browser app using OpenID Connect, they will need to authenticate themselves to your OP server. Going through the OIDC flow, your browser app will get an ID token containing an issuer/subject pair identifying the user.
It's up to you to determine how the user stays logged into your OP server, but as long as the user at least authorizes the browser app once:
http://openid.net/specs/openid-connect-core-1_0.html#Consent
then you can save that consent for all future requests by this browser app to login, and therefore maintain a persistent login.
You're going to have to consider how you're going to handle sessions management, but it sounds like you have some cookie thing going already so you might be able to use that (see this answer: OpenID sign in mechanism - Stay signed in ). Otherwise, you're going to end up with a situation where your browser webapp has to get a new id token all the time.
Also as Florent mentioned, there are security considerations you should consider when doing a public client thing that your browser based webapp would be. Example:
https://www.rfc-editor.org/rfc/rfc6749#section-10.16

REST API and client on same server, need API authentication?

First, let me describe the application: we are working on a web-based software which is some kind of custom help desk application. It requires the user to login (we use FOSUserBundle). After login the user is redirected to the dashboard. From the dashboard there is no more page reload, the frontend is build on Angularjs and the user can get anywhere within the application without page reload. You could speak of a single page application.
So the data that is presented to the user, is fetched from a rest api (we use FOSRestBundle). This works quite well at this point.
There is some kind of dilemma. Only our staff will access this application (for now). So a staff member needs to login to access the helpdesk. The data that is pushed to the frontend via angularjs is called via api, so the user that has just logged in needs to authenticate again on every request because of rest.
Problem: Since the backend runs on symfony2 let us just try to get the user object of the currently logged in user when an api call is made:
$this->get('security.context')->getToken()->getUser()
returns anon. that stands for anonymous, or
$this->getUser();
returns just null.
So the authenticated context seems to be gone when using the rest api. However when I call an action directly without rest, I can get user information.
So what we need is to secure our rest api and get user information on every api call. We don't want third party people to access our application, just staff. I am not familar with OAuth, but the user will be redirected to a third party page to Allow/Deny access to his data? This would not be an option for us.
Based on that information, do you have any suggestions or ideas how to secure the api and transport the user data so that getUser does not return null or anon. but the actuall logged in user?
there's another way to resolve your problem.
It's by using Certificates.
you can generate certificates then use Http tunneling (https obviousley), the server will ask for a certificate (you've to configure Apache for that but it's not a big challenge).
with this in place, you've to add a CertificateManageron the server side to ensure that the certificate is valid and to know who's calling the service (to be able to authenticate the user at each request), the CertificateManager(or what ever you'll call it) will probably have to be configured within you filters chaine (as known in the java world), et voilĂ 
Hop that help you,
Abderrazak
REST is stateless so you will have to send some kind of authentication/authorization in each request. You can use HTTP BASIC AUTH or something like OAuth.
Have a look at https://github.com/FriendsOfSymfony/FOSOAuthServerBundle
I'm kind of building our application in exactly the same architecture (RESTful API with Symfony2 back-end and AngularJS frontend.
Another way is to duplicate the api routes, so that you have the api routes protected by OAUTH and the api routes protected by the session, both of them pointing to the same controllers. The method was explained here: https://stackoverflow.com/a/22964736/435026