Search code examples
c#angularauthenticationasp.net-web-apitoken

Web API and Angular 5 Token Authentication - Get user info after log in


When i access my angular app, i get this:

access_token:"******************"
expires_in:59
refresh_token:"******************"
token_type:"bearer"

But now I would like to use the information of the user who logged in. My problem is that I can not because I do not have the user id between the token information.

This is my c# login from API:

//Varifying user credentials
    public bool Login(string userName, string password)
    {
        try
        {
            ServiceContext db = new ServiceContext();
            var userInfo = db.Users.Where(x => x.Username == userName).FirstOrDefault();
            if (userInfo != null)
            {
                string stringPwd = Encoding.ASCII.GetString(userInfo.Password);
                return stringPwd == password;
            }
            else
            {
                return false;
            }
        }
        catch (Exception ex)
        {
            return false;
        }
    }

This is my Authentication Service from Angular App:

@Injectable()
export class AuthenticationService {
constructor(private http: HttpClient) { }

login(username: string, password: string) {

    var data = "grant_type=password" + "&username=" + username + "&password=" + password;
    var reqHeader = new HttpHeaders({ 'Content-Type': 'application/x-www-urlencoded','No-Auth':'True' });
    return this.http.post<any>(`${environment.apiUrl}/token`, data, { headers: reqHeader })
        .pipe(map(user => {
            // login successful if there's a jwt token in the response
            if (user && user.access_token) {
                // store user details and jwt token in local storage to keep user logged in between page refreshes
                localStorage.setItem('currentUser', JSON.stringify(user));
            }
            return user;
        }));
}

This is my GrantResourceOwnerCredentials:

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {

        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        Accounts acc = new Accounts();

        //Authenticate the user credentials
        if (acc.Login(context.UserName, context.Password))
        {
            identity.AddClaim(new Claim(ClaimTypes.Role, acc.GetUserRole(context.UserName)));
            identity.AddClaim(new Claim("username", context.UserName));
            identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
            context.Validated(identity);
        }
        else
        {
            context.SetError("invalid_grant", "Provided username and password is incorrect");
            return;
        }
    }

I would like to display the username used for login. Can someone help me and give me some advice?

Thanks in advance


Solution

  • Modify your GrantResourceOwnerCredentials method like below

    You need to use AuthenticationProperties that you can add more parameters with your token data.

    And AuthenticationTicket will bind your added parameters to your token data and your will access those data in your angular app.

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
    
        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        Accounts acc = new Accounts();
    
        //Authenticate the user credentials
        if (acc.Login(context.UserName, context.Password))
        {   
            //If you want to display user's firstname, lastname, or picture then
            //The below method is for getting user from database by its username
            var user = acc.GetUserByUsername(context.UserName);
            string firstName = user.FirstName;
            string lastName = user.LastName;
    
            identity.AddClaim(new Claim(ClaimTypes.Role, acc.GetUserRole(context.UserName)));
            identity.AddClaim(new Claim("username", context.UserName));
            identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
    
            var props = new AuthenticationProperties(new Dictionary<string, string>
                        {                             
                             {
                                 "userName", context.UserName
                             },
                             {
                                 "firstName", firstName
                             },
                             {
                                 "lastName", lastName
                             }
                        });
    
            var ticket = new AuthenticationTicket(identity, props);
            context.Validated(ticket);
        }
        else
        {
            context.SetError("invalid_grant", "Provided username and password is incorrect");
            return;
        }
    }
    

    And add this method to below of GrantResourceOwnerCredentials

    public override Task TokenEndpoint(OAuthTokenEndpointContext context)
    {
        foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
        {
            context.AdditionalResponseParameters.Add(property.Key, property.Value);
        }
    
        return Task.FromResult<object>(null);
    }
    

    Output:

    access_token:"******************"
    expires_in:59
    refresh_token:"******************"
    token_type:"bearer",
    firstName: "Abc",
    lastName: "Pqr",
    userName: "Xyz"