5

this what i got in Claims shown in the picturei am using asp.net Authorization to log in with Angular js for client side ,i need to get Current user logged in

i need to get current User to save any operation in my logger Table, and httpcontext.session.current is null , is there is another way to save logged in user in session or some thing else to get it anytime

public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
    private readonly string _publicClientId;

    static ERPV02_03Entities db;

    public ApplicationOAuthProvider(string publicClientId)
    {
        if (publicClientId == null)
        {
            throw new ArgumentNullException("publicClientId");
        }
        db = SingleTonConText.Instance;

       _publicClientId = publicClientId;
    }

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();

        ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);

        if (user == null)
        {
            context.SetError("invalid_grant", "The user name or password is incorrect.");
            return;
        }

        ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
        OAuthDefaults.AuthenticationType);
        ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
        CookieAuthenticationDefaults.AuthenticationType);

        AuthenticationProperties properties = CreateProperties(user.UserName);
        AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
        context.Validated(ticket);
        context.Request.Context.Authentication.SignIn(cookiesIdentity);



    }

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

        }
        var data= Task.FromResult<object>(null); 
        return data;
    }

    public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        // Resourcee owner password credentials does not provide a client ID.
        if (context.ClientId == null)
        {
            context.Validated();
        }

        return Task.FromResult<object>(null);
    }

    public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
    {
        if (context.ClientId == _publicClientId)
        {
            Uri expectedRootUri = new Uri(context.Request.Uri, "/");

            if (expectedRootUri.AbsoluteUri == context.RedirectUri)
            {
                context.Validated();    
    }
        }

        return Task.FromResult<object>(null);
    }

    private static View_Emps GetUserInfo(string username)
    {
        var user = new View_Emps();
        try
        {
user = db.View_Emps.FirstOrDefault(p => 
                                       p.Emp_UserName == username);
    HttpContext.Current.Session.Add("user", user);


        }
        catch (Exception e)
        {
            throw e;
        }


        return user; 
    }

    public static AuthenticationProperties CreateProperties(string userName)
    {
        var user = GetUserInfo(userName);
        JavaScriptSerializer js = new JavaScriptSerializer();
            var res = js.Serialize(user);
        IDictionary<string, string> data = new Dictionary<string, string>
        {
            { "User", res }
        };
return new AuthenticationProperties(data);}}


public  void SaveLog( T Obj, string Operation)
    {



        string hostName = Dns.GetHostName(); // Retrive the Name of HOST  IpAddress
        string myIP = Dns.GetHostEntry(hostName).AddressList[0].ToString();

        var user = HttpContext.Current.Session["user"] as View_Emps;
        MyLogger.Data =  new JavaScriptSerializer().Serialize(Obj);
        MyLogger.OperationType = Operation;
        MyLogger.TableName = typeof(T).Name;
        MyLogger.DateTime = DateTime.Now;
        MyLogger.User_ID = user.Emp_ID;
        MyLogger.IP_Address = myIP;
        db.Loggers.Add(MyLogger);
        Commit();



    }
Ȝlaa A. Saleh
  • 87
  • 1
  • 1
  • 11

6 Answers6

6

You can get current login user in Api Controller from IPrincipal and you will no need to reference any namespace for it like,

...
var user = User;   //<= "User" comes from System.Security.Principal.IPrincipal
...

You can also get other properties from IPrincipal like

  • AuthenticationType
  • IsAuthenticated
  • Name

From the identity of such user like,

var authType = User.Identity.AuthenticationType;
var isAuthenticated = User.Identity.IsAuthenticated;
var name = User.Identity.Name;

Edit:

You can add your custom fields as claim to your identity in GrantResourceOwnerCredentials method like,

...
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
               OAuthDefaults.AuthenticationType);

oAuthIdentity.AddClaim(new Claim("UserId", user.Id));   //<= The UserId add here as claim
oAuthIdentity.AddClaim(new Claim("UserName", user.UserName));  //<= The UserName add here as claim

ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
                CookieAuthenticationDefaults.AuthenticationType);
...

And then in Api controller action method you can get this UserId like,

var userId = ((ClaimsIdentity)User.Identity).FindFirst("UserId");
var userName = ((ClaimsIdentity)User.Identity).FindFirst("UserName");

Edit 1:

Here I got UserId and UserName from claims.

enter image description here

And from angular js HTTP you can send your auth bearer token like

module.run(function($http) {
  $http.defaults.headers.common.Authorization = 'bearer TGAf8ViNUtzb9RP9OCBXHN4Ewm0dQbTMb6x4wJMgi4Wk8pq-QEQLIhp_W1A-9jQa7Rlqa60vsQ2ubbjUL0wGosEwaHFDlbdkQqXbOP_VlBJMxN2KnGQZnmvWZvpLPqMF-jpWzPDvBwtVHnh3AjLviPX0gPQjxZAC1ujIeB0p-QZ8yE1VCnLa8Xql01XDXlLVBCzk1UOqt_er-Gx6pL8SemayY8dqVVUgSZTYhcceLLuWQ-Cy3QATJmoJ41K-7ktAeUTz5H7V3ImlC_b8qnnN8sj7k7WRT51q27pUO4-bzJzkD4LGVvDUqaeAhBEqKyS9TkpMIFbRDMol5ZiJcp2vTunOOYP42Mw7GJv09ctoXegKkWo1LWDsSDxeWP5KQed_VGX193pZvQtvz06g2iyXwuP8Q6NaJcXTF43-M9p2HWgGuXT531YXv59euaWevj1AMJkazlZ61uzYi7KGLHKgCwzAMXLKwzBGK4QP0C4tqonowSdTttH93LBOJHjrDepk';
});

By using the above code at angular side your request will add auth token for each request via Http

learn more about $http

Edit 2:

Add those data as the claim in GrantResourceOwnerCredentials that you want to be carried over your unit of work repository like,

oAuthIdentity.AddClaim(new Claim("Id", user.Id));
oAuthIdentity.AddClaim(new Claim("UserName", user.UserName));
oAuthIdentity.AddClaim(new Claim("Email", user.Email));
oAuthIdentity.AddClaim(new Claim("PhoneNumber", user.PhoneNumber));

Then read those data in your controller method like

ClaimsPrincipal principal = Request.GetRequestContext().Principal as ClaimsPrincipal;
var claims = principal.Claims.Select(x => new { type = x.Type, value = x.Value });

var id = claims.Where(x => x.type == "Id").FirstOrDefault().value;
var userName = claims.Where(x => x.type == "UserName").FirstOrDefault().value;
var email = claims.Where(x => x.type == "Email").FirstOrDefault().value;
var phoneNumber = claims.Where(x => x.type == "PhoneNumber").FirstOrDefault().value;

ApplicationUser applicationUser = new ApplicationUser  //This model is pre generated by web api project and reside in `Models` folder
{
    Id = id,
    UserName = userName,
    Email = email,
    PhoneNumber = phoneNumber
 };

Now you are free to use this object applicationUser to pass in your unit of work repository.

er-sho
  • 9,581
  • 2
  • 13
  • 26
  • User.Identity.Name is null Too – Ȝlaa A. Saleh Jan 30 '19 at 13:48
  • View **Edit** section in answer and let me know :) – er-sho Jan 30 '19 at 13:57
  • i tried it but still null when i get them in my controller – Ȝlaa A. Saleh Jan 30 '19 at 14:24
  • kindly add breakpoint on variable `oAuthIdentity` and check the claims inside this variable in debug mode and let me know whats the claims added? – er-sho Jan 31 '19 at 06:09
  • yes that what i did it => User.Identity all his variables = null and Claims Empty yielded no results – Ȝlaa A. Saleh Jan 31 '19 at 10:13
  • no not here if claims not added while authenticating then you got null in User.Identity. i have to say that kindly add breakpoint on variable `oAuthIdentity` in `GrantResourceOwnerCredentials` method and check once in debug mode – er-sho Jan 31 '19 at 10:22
  • yes it added well and have values but when i try to get it in My controller become – Ȝlaa A. Saleh Jan 31 '19 at 10:36
  • ok means claims added successfully but only problem is for retireving, so please wait I'll try something to get those values. – er-sho Jan 31 '19 at 10:40
  • exactly ,Claims Became empty when i try to retrieving it – Ȝlaa A. Saleh Jan 31 '19 at 10:44
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/187645/discussion-between-laa-a-saleh-and-er-mfahhgk). – Ȝlaa A. Saleh Jan 31 '19 at 10:50
  • try this in your controller => `ClaimsIdentity claimsIdentity = User.Identity as ClaimsIdentity; var claims = claimsIdentity.Claims.Select(x => new { type = x.Type, value = x.Value });` and let me know the values inside above `claims` variable. – er-sho Jan 31 '19 at 11:06
  • also try this => `ClaimsPrincipal principal = Request.GetRequestContext().Principal as ClaimsPrincipal; var claims = principal.Claims.Select(x => new { type = x.Type, value = x.Value }); var id = claims.Where(x => x.type == "UserId").FirstOrDefault().value;` – er-sho Jan 31 '19 at 11:16
  • Ok I got the problem and that is you are not sending your auth bearer token from angular HTTP request so that's why all your claims are getting null. see in my screenshot in **Edit1** section I got userid and username successfully – er-sho Feb 01 '19 at 05:50
  • Heartly thanks man for your efort and helping me , i know it will be succes as bearer and token do not send in my request – Ȝlaa A. Saleh Feb 02 '19 at 02:13
  • So did you get claims after passing token to controller? – er-sho Feb 02 '19 at 04:15
  • No i am not traied it yet – Ȝlaa A. Saleh Feb 02 '19 at 21:25
  • First I suggest you that try to pass your token with http request from Postman and if you got success then try from angular and let me know. I'll wait for your response. – er-sho Feb 03 '19 at 01:36
  • Still null bro :( @ er-mfahhgk – Ȝlaa A. Saleh Feb 03 '19 at 14:55
  • Its working see the screenshot. But i also wonder how its not work for you. So tomorrow I'll take a session with you on TeamViewer or AnyDesk if you feel comfort. – er-sho Feb 03 '19 at 17:15
  • Its oky no problem send me at :alaaasaleh7@gmail.com – Ȝlaa A. Saleh Feb 03 '19 at 20:40
  • since dbcontext.current.session can not use it how to save that data to pass it to log function? – Ȝlaa A. Saleh Feb 04 '19 at 14:57
  • Add all those data that required to log function as claim in your grantresource method and in your log function read those claims and prepare your "View_Emps" and then save to db. – er-sho Feb 04 '19 at 16:31
  • I am using unit of work and repository , so i need a way to get the claims data at my repository , when i was using mvc i was getting from current session in my repository , so how to get it using api – Ȝlaa A. Saleh Feb 05 '19 at 01:04
2

In a MVC Controller:

var user = await _userManager.GetUserAsync(User);

In a API Controller, use this:

var user = await _userManager.FindByNameAsync(User.Identity.Name);

Make sure the user is authenticated with the authorize attribute in the controller, and in the beginning of your page:

[Authorize]
1

Review this Question Is it possible to set localStorage or Session variable in asp.net page and read it in javascript on the other page?

public  void SaveLog( T Obj, string Operation)
    {

        string hostName = Dns.GetHostName(); // Retrive the Name of HOST  IpAddress
        string myIP = Dns.GetHostEntry(hostName).AddressList[0].ToString();

        var user = HttpContext.Current.Session["user"] as View_Emps;

// instead of this .. u can this in local storage and remove it after log out or timeout // timer

        MyLogger.Data =  new JavaScriptSerializer().Serialize(Obj);
        MyLogger.OperationType = Operation;
        MyLogger.TableName = typeof(T).Name;
        MyLogger.DateTime = DateTime.Now;
        MyLogger.User_ID = user.Emp_ID;
        MyLogger.IP_Address = myIP;
        db.Loggers.Add(MyLogger);
        Commit();


    }
Mazen Ahmed
  • 100
  • 5
1
[Authorize]
[HttpGet("GetCurrentUser")]
public async Task<ActionResult<string>> GetCurrentUser()
{
    var UserName = User.Identity.Name;
    var user = await _userManager.GetUserAsync(User);
    return Ok("Current User: " + user);
}
  1. Annotate the controller or the endpoint with -> [Authorize]
  2. There are two solutions to get the currently logged in user.
    • Use: User.Identity.Name
    • Inject the UseManager class into the controller, then you can call on it the GetUserAsync(User) method (ClaimsPrincipal: User)
PeterPazmandi
  • 533
  • 10
  • 13
0
var UserName = User.Identity.Name;
var UserId = ((ClaimsIdentity)User.Identity).Claims.FirstOrDefault().Value;

It works well with that way but i had to Send token in header though

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Ȝlaa A. Saleh
  • 87
  • 1
  • 1
  • 11
  • 1
    That means my answer helped you to solve your problem. So no need to connect with TeamViewer or AnyDesk right? – er-sho Feb 04 '19 at 05:45
-2

you cannot use session in api call , each time you need to authenticate user you must send token of the user

you can read about JWT for authetication