Angular app protection and user authentication - javascript

Implementation of user authentication in Angular app means that application's javascript must be available to user before he is authenticated. That is the problem. What is the correct way to make this happen with Angular? Do I need to implement a separate app for authentication and then redirect users to the base app?

Authentication should be on server level. The angular app should be responsible for only the capturing of credentials, possibly encrypting it, and sending an authentication request to the server with those credentials. The server response(possibly a token) could be used for any further communications with the server to identify the logged in user and its available services.
If the application itself does not contain any private business logic, I don't see value in keeping the application away from the end user even before authentication. On that note, however, take a look at tasks that are used to minify javascript code. This may be second best :)

Related

How is nuxt/auth really secure?

Let's imagine a client opens your nuxt.js website on the index page. From there, they authenticate (you used #nuxtjs/auth-next for that purpose). Then they move to a secure page that only authenticated users can see. This secure page is a .vue file in your "pages" folder with middleware: ["auth"].
Now, how is this page really secure ?
I mean, couldn't a malicious user temper with the page and access it without being authenticated anyway ? Because the "security" in this scenario is only implemented on the client side right ? [Edit]
Your application being an SPA at the end, if you want to bypass a middleware with it's security checkup, you could disable the JS on the page. But then, since no content is generated directly, you won't see anything because it's not here (as a static file).
If your app is isomorphic (basically has a ssr: true), the auth module will still disable the access to those pages (you can double check).
At the end, the critical info is received when:
you do have a valid JWT token (after some login)
you submit an HTTP query to the backend
the backend acknowledges it and the token is valid
the backend gives you the sensitive info via an HTTP response
At the end, your client side code doesn't need to be secure. If somebody somehow hacks your client side state and reaches the sensitive page, he will still not have a valid JWT token since the verification still happens on the backend.
The one that can be generated only when sending the proper credentials to the backend and having the backend validating those.
Now, how is this page really secure ?
The protected content is served from a request if a valid access token has been provided by the client.
The protected content is provided at runtime.
Because the "security" in this scenario is only implemented on the client side right ?
The security is not only implemented on the client side.
The premise is: The access token has been obtained securely through an authentication flow with an auth-server.
I recommend to read more about auth flows if this sounds unclear.
Auth0 has some good documentation on different flows.
https://auth0.com/docs/authorization/flows
Then, what is the best way to show a complex page to authenticated users only ?
The content is provided at run-time. Server-side or client-side.
There are some setup guides here for Nuxt.
Here is the first (Auth0) I found from the list.
https://auth.nuxtjs.org/providers/auth0
I don't know how updated those guides are, but the auth service providers tend to have updated guides themselves.

NextJS auth with an external server

I'm working with auth in Nextjs, I'm wondering what is the best strategy to handle authentication in NextJS ?
Here my services structure :
If I understand well I have to handle the server side rendering in NextJS, so I understand I have to put cookies from my external server to my NextJS client, then handle the server side rendering checkings. To do that I assume I have to create connection between the NextJS server and the other services. Before dive more deeper in the subject I would discuss with you about the possibilities available to me. It seems the NextJS auth is a subject in plain development.
Any hint would be great,
Thanks
I've recently added an example with cookie auth which explains what you are trying to do on the frontend.
For the backend, optimally you'll have your API in an external server, apart from the server you use for rendering your Next.js app. This API will handle the database and the token creation business. Then the basics of the authentication are like this:
The client POST a request with username and password to the server.
The server gets the request and generate a token based on the data received.
If everything went okay validating the data, the server responds with the token, e.g., { token: "secrettoken" }.
The client receives the token and saves it in a cookie. Optionally you redirect the user to the /dashboard or /profile if everything is okay.
The client, on restricted pages, will check if the cookie exists and optionally validate that against the server, you do this last part in getInitialProps. If the cookie validation fails you redirect the user away.
I've created a small library to abstract this logic.
So in the end, your Next.js app shouldn't know what's happening in the server, it only should receive the token, save it, validate it, and redirect the user if something is wrong.
How you want to handle the token creation, on the external server, is up to you.
Check out this thread. There are several examples of how to do Authentication with JWT, OAuth etc throughout the thread. You'll see that the examples are utilizing getInitialProps and there are several examples utilizing cookies throughout to extract the Authentication tokens.
You'll have to write a custom server.js file using express.js to serve the tokens through your route requests. I'm assuming by "external server" you mean some third party Authenticator using OAuth or OpenId protocols to retrieve tokens. If so, you're right to say that you'll need to request the tokens (or Authentication mechanism) from those external services and then decide how you're going to utilize them in your own client. You'll probably be using getInitialProps to do what you need to do with your Authentication tokens in the client once you are rendering to the browser.
More examples of Authentication here -- one for firebase and another for Apollo.
Just to add to the answers if you want to use Auth0 specifically. In the interview on http://www.fullstackradio.com/112 around the 1:06 min mark Guillermo Rauch mentioned that if he were to implement authentication all over again he would use Auth0, so I created a minimal repo using Auth0 and Nextjs with Serverless functions.
Like #jolvera suggested there is an API in an external server, apart from the server used for rendering the Next.js app. This API is located in ./auth/auth.js. It handles the token creation business, and could be extended to handle the database.
The HOC component in ./utils/withAuth.js calls the auth.js lambda for the user information, and is only able to retrieve it if the client side is authorized. Otherwise the user information is undefined. Additionally there is an event listener similar to the one in with-cookie-auth which syncs logouts across tabs.
Also one other note, don't get confused with the Nextjs example on Auth0's blog. That example is extending the Nextjs server, and isn't the solution you want if you are deploying Next to serverless. It doesn't have the separation of concerns with page routing and authentication.

Authentication in SPA using Auth0 and clients node.js server

Background
I have two apps:
Angular2 Single Page Application
Node.JS with express
I'd like to authenticate and authorize users logging into Angular2 app, by consuming API exposed by express server. I'd like to use Auth0 as my IDP. I want the whole app (client + server) to be made-to-measure.
At the same time:
I don't want to use Auth0 Lock
I don't want to use refreshes and redirects (for fine UX and simplified flow)
I don't want to ship auth0.js library to Angular2 app (to minimize payload and client-side code complexity).
I would like to keep auth data returned by server in localStorage (as opposed to passport.js setting cookies and refreshing)
Preferably, I wouldn't want to set up database for these purposes, although it's possible.
Proposed architecture
Red arrows indicate authentication flow.
5 is a generic API request.
Actual question(s)
Are there any contraindications to using such architecture?
How do I achieve it and what do I need to pass through each of 4 requests/responses? (the simplest scenario and prerequisites)?
Are there any resources which will help me get better understanding of OAuth and authentication in general, for beginners in this field?
Q1
Given that OAuth2 uses HTTP redirects for a significant part of the functionalities it specifies, going with an architecture such as that one and imposing that many constraints will reduce the number of possibilities you can leverage. Besides that, I don't see any major problems.
Q2
Given you don't want to use redirects the OAuth2 flow that you need to use is the resource owner password grant (ROPC), mostly because of the four flows that OAuth2 provides it's the only one that would meet your requirements.
❌ Authorization code grant (redirect-based)
❌ Implicit grant (redirect-based)
✅ Resource owner password grant
❌ Client credentials grant (aimed at client applications that want to access an API on behalf of themselves and not of an end-user)
In request 1 and 2 you pass the username and password credentials, first to your own server and then to the authorization server. In requests 3 and 4 the access token resulting from a successful user authentication is delivered to the AngularJS application that can store it in localStorage for later use.
This meets your exact requirements, but it's not the most common architecture in use. Normally, the SPA would use the implicit grant to get the access token. Given this grant is optimised exactly for this purpose it can be implemented with good UX characteristics, however, it would indeed make use of redirects.
Q3
The OAuth2 specification itself is not that hard on the eyes and it would be the best resource I would recommend. For a more high-level and quick intro into the topic I would also recommend https://auth0.com/docs/protocols/oauth2.

Proper OAuth2 flow for public first-party clients

I'm a regular reader here at stack overflow but this is my first question.
I'm developing an authorization-server using the OAuth2 specs. And I just got stuck with how do I ensure the first-party client authenticity while using the password flow. I read many forums and this is what I got:
Javascript single-page clients
This blog post by Alex Bilbie, he states that to avoid the client_secret problem we should just:
It’s simple; proxy all of your API calls via a thin server side component. This component (let’s just call it a proxy from here on)
will authenticate ajax requests from the user’s session. The access
and refresh tokens can be stored in an encrypted form in a cookie
which only the proxy can decrypt. The application client credentials
will also be hardcoded into the proxy so they’re not publicly
accessible either.
But now this proxy can be accessed by someone impersonating my
angular app. And then I came across this blog post from Andy
Fielder: How Secure is the OAuth2 Resourc Owner Password Flow
for Single Page Apps. He basically says to rely on CORS to
avoid impersonating JS clients.
It is a good idea to use both approaches to secure my JS app?
Native Apps (Desktop and Mobile)
In the case of mobile apps, I only found cases for Authorization
Code and Implicit flows. This is not what I want, as the redirects
will compromise the user experience. So my thoughts on this is:
I will use the ROP flow and then register the client with a
client_id generated for this particular installation and attach it
to the user account, receiving the access_token and a
client_secret as response. Any other token request made by this
client MUST carry this credentials (as the client_id is specific
for the installation, I will be able to check if this client is
already authenticated). This way if someone uses any credential for
impersonating a client, or even registers a bogus client, I can take
mesures to revoke the user and client access.
I know that this can be overthinking, and I also know that some of this matters doesn't avoid anything. I just feel that is my job to protect my API as much as I can.
I would really appreciate your thoughts about this matters! Am I really overthinking? Should I just use the concept of a 'public client' and carry on?
Thank you all and happy coding!
First of all, this problem is not a common priority because most applications are developed first with website, and after with the API. This is probably the reason because no one knows how to deal first clients with oauth2, because everyone have developed other ways to do that and oauth2 is needed only to grant user access to third party applications.
Even if you have develop the oauth2 authorization server only for your first clients applications (thinking about a single authentication mechanism instead of developing many), you should try to develop the authorization code or implicit grant types. You will realize that you need a way to check what user is actually logged in.
The two common methods are:
user session (based on Cookies)
user access from localStorage (based javascript)
In either ways you need to check your application security, user session is vulnerable to CSRF, localStorage are vulnerable to XSS. There are a lot of articles about how to secure your website against either, so I will not suggest anything here, you just need to know that they exist.
Now that you choose your authentication method we can start to do some consideration about:
Javascript single pages applications
Proxy
Having a proxy that filter all requests in my opinion is like to have a door with the keys always inserted. It's useless even build the door.
However, for session based authentication it's the only way to do it. Allowing session authentication on your Rest API will open to CSRF security issues, so you need to have a proxy layer that get the user session, retrieve the access token from the session and do the request to the Rest API adding the Authorization header.
CORS
With this method you need to store the user access token in the localStorage, because the token is retrieved from the Js client directly.
Using CORS you are sure that other websites cannot do requests to your Rest API from a browser. But your first client need to be public (ie: it does not have a client_secret).
Native Apps (Desktop and Mobile)
In my first application I tried to use the same mechanism that you suggest to secure the auth flow. However that type of mechanism require that you identify every user client in an unique way. This is not possible in iOS for privacy reasons and with some probability it will denied in the future releases of Android. So you should rely on a public client and add only the client_id in your native application code.
This means that your native app client/your js client can be impersonalized? Yes, and there is no way to prevent this with oAuth2 resource owner password credentials grant type.
The main reason about this is because oAuth2 is not for authentication, only for third-party authorization, and that grant type was added only for specific third-party applications trusted enought to use directly the user password. You could read more about this argument here and here.
At the end
You still need a way to auhorize your user, and I think that the best you can achieve using oAuth2 is what Auth0 did.
Essentially this Saas manage your users with an oAuth2 server + OpenID connect, so you are always managing your users like its a third-party application and everything works fine.
Indeed, you can see on this page that for mobile applications they suggest to use a browser based login form, because the native one can be impersonalized by everyone that decompile your application, but if you wrap it into an authorization code flow it works fine.

creating a multitenant SPA backed by restful web services

I am trying to create a multi tenant SPA (Single Page App) using HTML5/Javascript. This app will invoke restful webservices for data updates. Below is in illustration to the architecture:
These are my challenges:
Identity : How will a service know that a request coming from a client side JS corresponds to a particular schema in the database? May be I can send an "APPID" token? But, this can be spoofed easily by the end user?
Connection Pooling : If tomcat pool is relied upon for connection pooling, how do I ensure that connections created using "app1" credentials, which has access to APP1 schema are returned to the webservice when it handles requests from App1 JS? I can possibly, just create one database account which has access to all schemas, but this can probably become a compliance issue.
Should I just deploy multiple copies of the webservices? Say, app1 JS queries services.app1.com and app2 JS queries services.app2.com? This would probably solve the above two issues, but I don't think it is a multi tenant solution anymore.
This is normally accomplished by a token that is authenticated. This is normally handled by a standard session cookie (implemented by whatever application server you are using), or something less stateful (like an OAuth bearer token) that gets validated on each call. This is ultimately the same solution, one using a cookie (which is implemented via a HTTP header), the other is using an Auth http header. Regardless, what basically happens is that each user is issued a magic string, which is authenticated on each call as belonging to a particular set of credentials.
It is fairly similar to your "APPID" in theory, the difference is that the tokens are opaque, and very likely unguessable do to their length and complexity (before the heat-death of the universe), and thus are effectively secure. The difference is that you hold the binding between the token and which "APPID" on the server side, not on the client side.

Categories