Authentication in Angular and Parsing Cookies

Responses (0)


Newline logo

Hey there! 👋 Want to get 5 free lessons for our The newline Guide to Angular Universal course?

Clap
0|0|

Our applications are going to have authenticated users, but how do we pre-render SSR content that is protected only for users of our app?

That's what I'm going to show you in this post.

Remember that with Angular Universal we can parse incoming HTTP requests on our server of our Angular app and then use that data to show content, depending on who is looking at it.

To do this, we inject REQUEST from @nguniversal/express-engine/tokens - and this will let us parse the request from our Angular code but on the server before we render the content.

Imagine we have the following UserService on our server:

Unfortunately, the request object you have in Angular is not equivalent to what you have in Express.js. There is no .cookies field to easily retrieve a cookie's names and values.

We do have request headers, though, so we can extract the cookies that way.

Also in the code above, we have a MongoService which lets us access a database - again, on the server, but still in our "Angular" code - as well as a decrypt function, which lets us access to cryptography functions.

Reading the Headers#

Cookies are sent by the browser as an HTTP header called cookie. This header contains cookie names and values delimited by the ; character: cookieName=value;cookie2=value2;andSoON=andSoOn.

Let's implement the getCookie(name) method that retrieves the value of that header, splits it by the ; delimiter, and returns the value of a particular cookie specified by the function's parameter:

Above, we decode the cookie string, and then store it in an object cookies.

We can use that function to set up a loggedInCookie object field:

Now, to create an observable representing the logged-in user's ID, you can either decrypt the ID value if it's present or return null:

While it's great that we can get the userId - we probably want to use that id for something more interesting. For example, we might want to fetch the user object or check for permissions or render some special content.

For now, let's fetch the whole user from the database. We'll use this userId to build an observable representing the currently logged-in user:

The code above creates the currentUser$ observable by piping userId$ to the mergeMap() operator. Within mergeMap(), you retrieve the given user's data from MongoDB or return null if userId is not present (which means the user is not authenticated).

Now that we have this currentUser$ observable, we can implement other helper functions for example, we can add isLoggedIn or getFavorites to our UserService:

Angular Universal is incredibly powerful in that it lets us access server-side content when rendering our Angular apps. To learn more, check out: Mastering Angular Universal: Build Blazing-fast Server-Side-Rendered Angular Apps.


Clap
0|0