how to implement the authentication in Single Page Application? - asp.net

As the title says,I want to build a App that run in browser with a Single Html page.but how to implement the Authentication.and my solution is:
the server-side is all the RESTful APIs,which can used by multiple Platform,web ,mobile side ,etc.and every API that need auth will be get a token to parse,if the API does not get a token return 401.
cuz my first practise is in the browser,so I need to request for the token to get login,and when the app needs to request the auth-APIs,I will put the token in the header for requesting...
and my questions is : does it safe enough? any other better solution?

No it's not safe enough if the token is accessible through javascript for the same reason that you should set your cookies to http only and restrict to ssl.
If a hacker can inject javascript into your app, it can steal the token and use it from their machine.
For that reason I suggest you use a secure, http only cookie instead of the token when using a website.
If your API is going to be accessed from a native mobile app then you could add a token to each url.
Having a custom header in the http request might cause issues with certain proxies which might not pass all headers through.
A cookie is nothing more than a standardised http header so you might as well reuse that.
What you could also consider using is OAuth if you're going to allow 3rd party apps access to parts of your API.
There is no reason why you could not use cookies for browser based clients and an ApiKey query parameter for other clients.

Related

How to attach Authorization header when redirecting POST request?

We have a third party service that implemented single-sign-on on some route to it’s web-app.
In order to use this single-sign-on, we provided with a POST API, and we need to pass on that route some credentials- including an organization secret that we got from him (yes, we need to pass it in query params), and the user’s email address.
In order to not to expose credentials over the browser, we tried to mimic that request by creating our own backend endpoint, and return the same result as their enpoint (kind of a proxy) with redirection (status 307 with Location header) cause there API returns plain HTML.
It seems like when client send a post request with redirection he can’t add the authorization header (JWT) required by our backend to operate (backend return Authorization required). the request is been done to our server and the result is redirection to another server.
How can we bypass it? Or maybe we can secure it with different approach?
I know that the header is usually been removed for a good reason, who knows where I can be redirected to?
but can't I tell him somehow that I trust the redirection?
We tried to use phantom-form only to use from submit post. We tried to make our endpoint to be GET and making the redirection other way (react-router) but I think that natively js does not allow to attach Authorization header.
I thought it would be a common pattern, but I didn't find someone that talks about it exactly, since we are trying to query our backend and not some external redirection API.

SSO for cross domain

I have two domains
Example :
a.com and b.com
I try to implement SSO Cross-domain authentication for these two websites
I refer to this link reference How youtube gets logged in to gmail account without getting redirected? to implement like Gmail and YouTube
I have doubt about that
How to send tokens from one domain to another domain using iframe
How to pass tokens in a secure way
If I use an intermediate domain how to prevent that domain call for accessing cookies value I want to set the cookies in the second domain
Please help me to implement I searched but the sample code is not available in asp.net
have you tried this method?
Using Reverse Proxy
As #David suggested, use a reverse proxy like Nginx or HAPorxy to serve both the applications from the same domain - protocol://host:port. All three things should be equal.
Using cookies instead of LocalStorage
If you use cookies instead of LocalStorage, then host ports do not participate in determining site policy. So two application running on the same host but the different port will share cookie without any extra work. To protect the cookie, use an HTTP-only cookie, same-site cookie.
Using URL to share - IFrame only
If you are using iFrame, then you can use URL to share the token. When the outer window is loading the iFrame, send this information via hash like http://localhost:8081/somepage#token=1234
Using hash will allow the page to send data to an inner page without being sent over the wire.
Using window.postMessage - IFrame only
Using window.postMessage, you can simply pass the required data to the inner window/iFrame. As long as you control both the endpoints, you can easily do cross-domain message sending.
In the end, it really depends on your security requirements, ease-of-maintenance, etc.
The best of this is using oAuth https://oauth.net/ provides a comprehensive definition of this.
There are many open-source implementations of oAuth consumer and server available.
The concept is that a third URL will authenticate and maintain the primary session and pass tokens via URL on redirect. The consumers can utilize tokens to request the server for details directly.
Overall benifit is that you will get implementations via open-source communities in a language of your choice, and you will be able to utilise third-party logins. There are other standards you can look into as well are SAML , OpenID and LDAP and products like shibbobleth,CAS and Azure AD.

Authentication for SPA hosted on same domain as API leveraging SameSite cookies

I am thinking about how I will implement authentication in my react application and even after hours of reading I still have few questions. Please provide any information you think could benefit me I would like to really understand the problem it could be that my line of reasoning somewhere implies I don't fully understand something I would appreciate if you could point out where I am wrong.
Infrastructure:
SSR React app served behind reverse proxy on <domain_name>
.NET 5.0 api server using asp.net identity served behind reverse proxy on api.<domain_name>
Reverse proxy provides SSL so https:// on both
General information:
I need to support external logins (Google, Facebook etc)
Paying for Auth0, Okta etc is not an option
No 3rd party apps are going to authenticate against me
Client is web browser
I don't need to support outdated browsers
Questions:
Do I need IdentityServer4 at all? I am never going to act as an authentication authority for 3rd party apps.
I can still support external logins without using IS4 right? I just need to handle redirect callback I can see there are methods such as GetExternalLoginInfoAsync, ExternalLoginSignInAsync which should make the job easier.
The reason why every SPA authentication tutorial recommends Auth Code + PKCE is because they assume you want to be authentication authority, don't have API on the same domain, or were written before SameSite cookies existed?
My plan is to write a custom login route assigning SameSite cookie and that's it. This makes client-side code super simple no shenanigans with adding access tokens to headers before making calls.
Is it possible? I found few articles describing something very similar but I am not sure.
With a setup like that is there something that is just not going to be possible? Like remote logout, banning users, or whatever you can think of.
You don't have to implement IS4 if you don't want to (especially since IS4 will have its support shut down in November 2022). You can just read the OAUTH2 documentation and implement the routes you need and still be OAUTH2 compliant.
You will have only one client (your react app) so no dynamic client registration, just the 2 following routes:
the authorization endpoint to get an authorization code when the user successfully authenticated himself using an external provider. This authorization code has to be used ONLY ONCE in the next route.
the token endpoint to get an access token and a refresh token using the authorization code given above or a refresh token given before. If the same authorization code or refresh token is used twice, you have to revoke the tokens given in the first call because this should not happen.
With a setup like that is there something that is just not going to be possible? Like remote logout, banning users, or whatever you can think of.
Besides these 2 routes you are free to implement whatever you want. Like a route to allow user to revoke all of his sessions.
To answer more precisely to your questions:
Do I need IdentityServer4 at all? I am never going to act as an authentication authority for 3rd party apps.
No you don't need it if you don't know exactly why you need it. It does not have anything to do with the fact that you are not going to act as an authentication authority for others clients.
I can still support external logins without using IS4 right? I just need to handle redirect callback I can see there are methods such as GetExternalLoginInfoAsync, ExternalLoginSignInAsync which should make the job easier.
Yes you can, as long as you store the authorization code and the refresh token when the user successfully signed in using the external provider.
The reason why every SPA authentication tutorial recommends Auth Code + PKCE is because they assume you want to be authentication authority, don't have API on the same domain, or were written before SameSite cookies existed?
I would assume that they are oriented Oauth2 compliance. But if you don't need nor want to implement OAuth2 framework, then don't. But in my opinion you should, it is really easy to implement.

IdentityServer4 Web Login via id_token or access_token

Context
I'm building a hybrid native/web app. Part of it will be API driven, and part of it will be webviews showing an existing website.
Once logged in with my OIDC SDK (Amplify/AppAuth), I can access the user's id_token and access_token.
However, because the webviews used in the SDK are not controllable, I cannot reuse the cookies generated by my identity server.
Question
For the reason above, I'm trying to login a user from their id_token or their access_token. (both are JWTs)
I believe this isn't supported by IdentityServer4, but I am looking to implement something myself.
What I have found so far:
1) id_token_hint
OpenID Connect Core 1.0, Section 3.1.2.1, id_token_hint parameter:
OPTIONAL. ID Token previously issued by the Authorization Server being passed as a hint about the End-User's current or past authenticated session with the Client. If the End-User identified by the ID Token is logged in or is logged in by the request, then the Authorization Server returns a positive response; otherwise, it SHOULD return an error, such as login_required. When possible, an id_token_hint SHOULD be present when prompt=none is used and an invalid_request error MAY be returned if it is not; however, the server SHOULD respond successfully when possible, even if it is not present. The Authorization Server need not be listed as an audience of the ID Token when it is used as an id_token_hint value.
If the ID Token received by the RP from the OP is encrypted, to use it as an id_token_hint, the Client MUST decrypt the signed ID Token contained within the encrypted ID Token. The Client MAY re-encrypt the signed ID token to the Authentication Server using a key that enables the server to decrypt the ID Token, and use the re-encrypted ID token as the id_token_hint value.
According to this optional spec of OpenID, I should be able to use the id_token on the /authorize endpoint to login the user. I know this isn't implemented in IdentityServer4, but I'm looking at AddCustomAuthorizeRequestValidator to do that. However I'm not sure how to "get a user from their id_token" in the code. Do you have any pointers?
2) using AddJwtBearerClientAuthentication
This method sounds like I could authenticate from my access_token, but I can't find much documentation on how to use it.
THE PROBLEM
Let me know if I am misunderstanding requirements, but it feels like you have 2 different apps and are trying to make them feel like a single integrated set of screens.
The default behaviour will be as follows since web views are private browser sessions and cannot use system browser cookies. You want to prevent the second step since it is a poor user experience:
User signs in to the mobile app
Whenever a secured web view is invoked, there is a new private browser session with no auth cookie, therefore requiring a new login
COMMON APPROACH: SUPPLY A TOKEN TO THE WEB VIEW
It can be common to forward the mobile token to the web view, if the two apps are part of the same user experience. If required, extend the mobile app's scopes to include those for the web app.
You should not need to issue any new tokens or change the security model of either app. But the mobile and web apps need to work together on a solution.
POSSIBLE WEB VIEW SOLUTION FOR A SERVER SIDE WEB APP
This might be the simplest option:
Provide new .Net Core web back end entry point URLs that require tokens instead of cookies
The mobile app could then call those endpoints from web views, and supply its own token in the Authorization Header of the web view request
The web back end could then forward mobile web view requests to your Web APIs
The code to add the Authorization Header to a web view request may be a little tricky but there are ways to do it:
Android
iOS
POSSIBLE WEB VIEW SOLUTION FOR AN SPA
An option that works for Cookieless SPAs is for the web view to ask the mobile host app for an access token via a Javascript bridge. Some code of mine does this for a cookieless SPA:
Web UI Code to Call the Mobile Host
Android Code
iOS Code
You can clone / run the mobile github repos from your local PC to see the solution. I will be writing up some notes on this in my blog's Mobile Web Integration Post.

Where the API Token should be put in standard form? Header or URI?

I'm developing an API using ASP.Net WebAPI, and authorizing clients with an access token. I want to know which source is more standard to put the access token? Headers, Uri or Body?
For example in Instagram API, clients should pass access token in uri as a query string. But I think in Twitter API the request must include an Authorization header.
Let me know if there is an standard rule.
Security related information such as an API Token go in the Authorization header. That is what it is designed for.
Putting api keys in the URI increases the chances of the API keys getting stored in the log file and it makes public caching far less effective.

Resources