Is there a way to get Current User in Api Controller
Asked Answered
S

6

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();



    }
Serin answered 30/1, 2019 at 13:16 Comment(0)
S
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.

Sloatman answered 30/1, 2019 at 13:28 Comment(23)
User.Identity.Name is null TooTripartite
View Edit section in answer and let me know :)Sloatman
i tried it but still null when i get them in my controllerTripartite
kindly add breakpoint on variable oAuthIdentity and check the claims inside this variable in debug mode and let me know whats the claims added?Sloatman
yes that what i did it => User.Identity all his variables = null and Claims Empty yielded no resultsTripartite
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 modeSloatman
yes it added well and have values but when i try to get it in My controller becomeTripartite
ok means claims added successfully but only problem is for retireving, so please wait I'll try something to get those values.Sloatman
exactly ,Claims Became empty when i try to retrieving itTripartite
Let us continue this discussion in chat.Tripartite
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.Sloatman
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;Sloatman
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 successfullySloatman
Heartly thanks man for your efort and helping me , i know it will be succes as bearer and token do not send in my requestTripartite
So did you get claims after passing token to controller?Sloatman
No i am not traied it yetTripartite
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.Sloatman
Still null bro :( @ er-mfahhgkTripartite
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.Sloatman
Its oky no problem send me at :[email protected]Tripartite
since dbcontext.current.session can not use it how to save that data to pass it to log function?Tripartite
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.Sloatman
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 apiTripartite
W
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]
Wolframite answered 4/1, 2021 at 14:42 Comment(0)
I
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();


    }
Ionization answered 30/1, 2019 at 14:14 Comment(0)
A
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)
Arbitrator answered 7/10, 2021 at 9:33 Comment(0)
S
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

Serin answered 3/2, 2019 at 16:22 Comment(1)
That means my answer helped you to solve your problem. So no need to connect with TeamViewer or AnyDesk right?Sloatman
L
-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

Leucomaine answered 1/2, 2019 at 13:22 Comment(2)
User will always be nullLeucomaine
5adt minus 😂😂Tripartite

© 2022 - 2024 — McMap. All rights reserved.