Okay.
We're going to add another couple of endpoints in here because with our API identity endpoints we can
get user information.
And if we do take a look back at the documentation and take a look at one of these other endpoints,
the Get manage info.
Then we can go and get the information about the user who's currently logged in the user we have a cookie
for and find out their email address.
And is the email confirmed?
Okay, that's fine, but perhaps we want to send more information back to the client, especially when
it comes to looking at the roles a bit later on, because we'd also like that information to come back
from an info endpoint.
And if we go and test that endpoint, and we take a look at the get default user info that I've got
here, and we take a look at the API manage info that's going to call that endpoint for the current
user.
We're logged in as the user that we have a cookie for, which in this case it's going to be Tom because
that's the one I just clicked on to sign in.
And I click send.
Then we can see that we get Tom's email back and that email is not confirmed.
Of course, because it's not a valid email anyway.
If I log in as a different user and let's go back to Bob, for instance, and click send and we get
the default user info again, what we should get this time is Bob's email address coming back.
So great.
Our authentication system is working.
We can log in using the user that we have registered and one of the ones that we've seeded.
But I'd like to get a bit more information back about the user.
When we do log in and we get a cookie, that's all we get.
We can't interrogate that cookie from our react client because it's an HTTP only cookie, which means
we cannot access that from JavaScript.
So whatever happens when a user logs in, we're going to have to call another endpoint.
And since the one that API endpoints has provided to us doesn't give us much information and we cannot
customize this, then we'll create our own endpoint to get information back.
Also, when it comes to removing the cookie from the browser, then the API endpoint does not actually
provide us with a log logout endpoint.
So we need to do something for that as well.
So let's go back to VS code.
And we'll go back to our account controller.
And we'll add another couple of things inside here.
So we're going to have an HTTP get.
And this is going to be for user info.
And we'll give this public async task.
And it's going to be an action result.
And we'll use Get user info as the method name.
We won't take any parameters because we can get the user from the cookie.
Now it would be tempting to say let's make this an authorized endpoint.
And if we wanted one of these endpoints to only be able to be called if the user was authenticated,
then we could use authorize as an attribute inside here.
And could we do that for this endpoint?
Yes we could.
And what would happen if an anonymous user called this end point, then this would return a 401 unauthorized.
And we will use this for other endpoints later on.
But we're not going to use it for this one.
And the reason being is that when our application starts up, our react application starts up, either
a user refreshes the browser or they've gone away and come back.
Then one of the things we'd want to do is persist their login.
If they've got a cookie in their browser, we would like to persist their login status now, because
our react client doesn't maintain a connection with our API, the only way we can do that is by using
the cookie in the browser to go and do something on our API, and we'll use it to go and get the user
info.
But because we cannot use the cookies in the browser from our react application, we cannot even check
to see if there is a cookie related to authentication in the browser.
The only way we can find out is by making a request to the API.
Now, when our application or when I use a refreshes the page, I don't really want to.
If they're just logged in anonymously or not logged in, I should say I don't really want to display
a toast every time they refresh the browser saying, hey, you're not authenticated or give them an
error.
401 error.
I'd rather that not happen.
So for this one, we'll do not that we won't make this an authorized endpoint, and we'll check a different
way to see if we do want to send back any information about the user.
Now, one of the things we get inside our controller is a user object.
And if we use user period then we can see the different information we can get about this user.
And if we use the user identity then one of its properties is is authenticated.
And when a user makes a request to this endpoint, then one of the features of an API controller is
it populates this user object.
If the user posts a cookie with the request.
So this controller endpoint will be able to check to see if this user is authenticated, and we'll check
to see if the user is not authenticated by making that equal to false.
And I'll just use the optional property here and if it is false, then we're not going to return unauthorized.
We're simply going to return no content, which sends back a 204.
No content, which is a successful request, which means it will not spit out an error on our client's
browser.
If they are authenticated, then we're going to return some user information.
So I'll use var user equals and then await.
We'll use our sign in manager again.
Again we'll get the user manager.
And we'll use the Get user async method.
And we'll pass in the user and user with a capital U.
Because this takes what is if I hover over the user then this is a claims principal.
And the get user async method is asking for a claims principal.
So we can just use what we get from our controller there for our user in lowercase u.
And if the user is equal to null at this point, then we are going to return unauthorized.
But our user should not be null at this point if we do have a claims principle for that user.
This is really just for our compiler, so we don't get any errors when we try and use the user, because
this could possibly be null.
And then we'll get hold of the roles for the user.
So once again we'll use the await sign in manager and the user manager.
And then we'll use the Get roles async method and pass in the user.
And then from this we'll return okay.
And we won't create a type for this.
We'll just create what's referred to as an anonymous object.
So I'll say new.
And on the next line I'll open curly brackets for an object.
And we'll specify user dot email.
The user dot username will just return that as well just as an example of returning things.
And we'll also specify roles equals user dot equals roles.
And close this off with a semicolon.
We'll also create another endpoint inside here as well.
This is going to be an HTTP post.
And we will give it a parameter of log out and we'll say public async task.
And again we'll just use Actionresult here without a type.
And we'll just call this method log out.
And inside here we'll use await and sign in manager.
And this is the reason for using sign in manager inside this controller rather than just the user manager
because this one has a sign out async method.
And if we take a look at what this does well, it doesn't give us much detail.
It signs the current user out of the application.
But what it also does is it removes the cookie from the user's browser as well.
We can't do this client side.
We cannot touch the cookie in the client's browser from the react application.
We have to do everything server side for that, and that's what this method does.
And then I will return no content from this because it's an HTTP request.
We have to make an HTTP Response.
So let's open up the terminal.
And too many warnings there for my liking.
I'm just going to restart the API controller and make sure it starts cleanly without any warnings.
And we'll go back and let's take a look at the get custom user info this time.
So it's going to API account user info.
Click send.
And we can see that we've got the email of Bob at test.com, same as the username.
And then we've got our array of roles.
And Bob is only in one role which is the member.
And if we take a look at the equivalent for the admin, there's a login method here for admin, which
is just the email.
As admin I'm going to say email at test.com and the same password and click send.
We get the 200 okay.
And if we take a look at the custom user info then we should find that the admin is in the member and
the admin role.
Excellent.
And just to finish off, actually there's a couple of requests in here to make sure that we cannot register
To a user with a duplicate username or email address.
I don't need that username there, so I'm just going to remove that and click send.
And we can see that the email bob at test.com is already in use.
And we get the same for the duplicate username as well.
That's fine.
I'm going to say that's okay for our response.
And we've already seen what happens if we try and use a weak password.
Again, I don't need that username there.
And click send.
And then we get the password validation coming back here as well.
So great.
That's our identity specific endpoints taken care of.
I've got a couple of others down here in this postman requests for this section.
And that's to get an address and update an address.
It's not something we're going to need immediately because it's more related to our checkout.
But we'll also cover adding these endpoints inside here.
Since we're working with our API controller, we'll also take a look at how we can populate a user's,
let's call it shipping address and retrieve it as well.
And we'll take a look at that next.