If user is authenticated via google, I need to get his profile picture.
If user is authenticated via facebook I get his profile picture with this code:
var info = await _signInManager.GetExternalLoginInfoAsync();
var identifier = info.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
var picture = $"https://graph.facebook.com/{identifier}/picture"; // 3
So, which code I need to use in 3 line for getting user's profile picture in case user is authenticated via google?
Accessing user profile picture, full solution.
Stack:
Asp Net Identity 4 v4 + Asp Net Identity + Google People Api
Steps
1. Preparation
1.1 I'm using default HttpClient to generate HTTP requests to Google API
1.2 Install NUGET System.Net.Http.Json to ease serialization.
1.3 Use a [json to c#] tool, to create a DTO like this:
/// <summary>
/// 🟡 official docs.
/// https://developers.google.com/people/api/rest/v1/people#Person.Photo
/// </summary>
public class PeopleApiPhotos {
public string resourceName { get; set; }
public string etag { get; set; }
public List<Photo> photos { get; set; }
public class Source {
public string type { get; set; }
public string id { get; set; }
}
public class Metadata {
public bool primary { get; set; }
public Source source { get; set; }
}
public class Photo {
public Metadata metadata { get; set; }
public string url { get; set; }
}
}
2. Identity Server: when users confirms external info data, send http get request, to retrieve avatar picture url:
Identity Server with Asp Net Identity > Login > OnPostConfirmationAsync: FULL METHOD
public async Task < IActionResult > OnPostConfirmationAsync(string returnUrl = null) {
returnUrl = returnUrl ? ?Url.Content("~/");
// Get the information about the user from the external login provider
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null) {
ErrorMessage = "Error loading external login information during confirmation.";
return RedirectToPage("./Login", new {
ReturnUrl = returnUrl
});
}
// try to get profile picture
string pictureUri = string.Empty;
if (info.LoginProvider.ToLower() == "google") {
var httpClient = _httpClientFactory.CreateClient();
string peopleApiKey = _configuration["GoogleApiKey:PeopleApiKey"];;
var googleAccountId = info.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
var photosResponse = await httpClient.GetFromJsonAsync < PeopleApiPhotos > (
$ "https://people.googleapis.com/v1/people/{googleAccountId}?personFields=photos&key={peopleApiKey}");
pictureUri = photosResponse ? .photos.FirstOrDefault() ? .url;
}
if (ModelState.IsValid) {
// Cria usuário
var user = new AppUser {
UserName = Input.Email,
Email = Input.Email,
FirstName = Input.FirstName,
LastName = Input.LastName,
ProfilePictureUrl = pictureUri
};
var result = await _userManager.CreateAsync(user);
if (result.Succeeded) {
result = await _userManager.AddLoginAsync(user, info);
if (result.Succeeded) {
_logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider);
var userId = await _userManager.GetUserIdAsync(user);
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page("/Account/ConfirmEmail", pageHandler: null, values: new {
area = "Identity",
userId = userId,
code = code
},
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", $ "Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
// If account confirmation is required, we need to show the link if we don't have a real email sender
if (_userManager.Options.SignIn.RequireConfirmedAccount) {
return RedirectToPage("./RegisterConfirmation", new {
Email = Input.Email
});
}
await _signInManager.SignInAsync(user, isPersistent: false, info.LoginProvider);
return LocalRedirect(returnUrl);
}
}
foreach(var error in result.Errors) {
ModelState.AddModelError(string.Empty, error.Description);
}
}
ProviderDisplayName = info.ProviderDisplayName;
ReturnUrl = returnUrl;
return Page();
}
2.1 Identity Server with Asp Net Identity > Login > OnPostConfirmationAsync: HIGHLIGHT:
❗️ this is only a little part from full method above.
Checks if external provider is Google, and use [NameIdentifier] and [Google Api Key] to reach People Endpoint.
// try to get profile picture
string pictureUri = string.Empty;
if (info.LoginProvider.ToLower() == "google") {
var httpClient = _httpClientFactory.CreateClient();
// ApiKey can get generated in [Google Developers Console](https://console.developers.google.com/apis/credentials).
string peopleApiKey = _configuration["GoogleApiKey:PeopleApiKey"];;
var googleAccountId = info.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
var photosResponse = await httpClient.GetFromJsonAsync < PeopleApiPhotos > (
$ "https://people.googleapis.com/v1/people/{googleAccountId}?personFields=photos&key={peopleApiKey}");
pictureUri = photosResponse ? .photos.FirstOrDefault() ? .url;
}
3. Identity Server > Profile Service Implementation:
public async Task GetProfileDataAsync(ProfileDataRequestContext context) {
var sub = context.Subject.GetSubjectId();
var user = await _userManager.FindByIdAsync(sub);
var principal = await _claimsFactory.CreateAsync(user);
var claims = principal.Claims.ToList();
claims.Add(new Claim(JwtClaimTypes.GivenName, user.FirstName));
claims.Add(new Claim(JwtClaimTypes.FamilyName, user.LastName));
// Insert a new claim, that gets ProfilePictureUrl persisted in my app user in database.
claims.Add(new Claim(JwtClaimTypes.Picture, user.ProfilePictureUrl));
context.IssuedClaims = claims;
}
4. Acessing profile user in ReactJS Frontend:
To get user profile data in frontend, i'm using OidcClient-js
// here i'm using oidc-client.js
// user object is loaded with user full data.
let profilePictureUrl = user.profile.picture;
Thanks to #DaImTo response.
People.get method returns a person object which contains
Your user needs to be authenticated with the profile scope.
Raw http request
GET https://people.googleapis.com/v1/people/me?personFields=photos HTTP/1.1
Authorization: Bearer [YOUR_ACCESS_TOKEN]
Accept: application/json
response
{
"resourceName": "people/117200475532672775346",
"etag": "%EgQBAzcuGgQBAgUHIgxHcHNCRHZycjVkZz0=",
"photos": [
{
"metadata": {
"primary": true,
"source": {
"type": "PROFILE",
"id": "1172004755672775346"
}
},
"url": "https://lh3.googleusercontent.com/a-/AOh14GhroCYJp2P9xeYeYk1npchBPK-zbtTxzNQo0WAHI20=s100"
},
{
"metadata": {
"source": {
"type": "CONTACT",
"id": "3faa96eb0baa4be"
}
},
"url": "https://lh6.googleusercontent.com/-vuhaM1mUvwE/VFOBzFDW-TI/AAAAAAAAAAA/izR9rgfDIyoVoHd7Mq_OJmdbwjhEnfhEQCOQCEAE/s100/photo.jpg"
}
]
}
Note: You can also get this information from the userinfo endpoint however Google does not guarantee that they will send the claims everytime you make the request so IMO its best to go though the people api.
Related
I'm trying to learn how to use authentication and SignInAsync via an API. For some reason, my code works only if I call the API from Postman or from Swagger, but not when I call it from code in the front-end.
To test this, I created two small projects: a web razor pages front end and a simple API. The API has the 3 possible POST requests (TestLogin, TestLogout and TestVerify) as show below:
[Route("api/[controller]")]
[ApiController]
[Authorize()]
public class LoginTestController : ControllerBase
{
[AllowAnonymous]
[HttpPost("TestLogin")]
public async Task<ActionResult> TestLoginAction([FromBody] LoginData loginData)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, loginData.UserName),
new Claim(ClaimTypes.Role, loginData.UserRole)
};
var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var principal = new ClaimsPrincipal(identity);
if (principal is not null && principal.Identity is not null)
{
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
return Ok("Successfully logged in.");
}
else
{
return BadRequest("Login failed.");
}
}
[HttpPost("TestVerify")]
public ActionResult TestVerify()
{
var user = User.Identity;
if (user is not null && user.IsAuthenticated)
return Ok($"Logged in user: " + user.Name);
else
return Ok("No user logged in. Please login.");
}
[HttpPost("TestLogout")]
public async Task<ActionResult> TestLogout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return Ok();
}
}
In my Program.cs, I add the cookie authentication
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie();
and
app.UseAuthentication();
app.UseAuthorization();
In my front-end razor page, I called the APIs this way using this code:
public string Message { get; set; }
public async Task OnPostLogin()
{
var client = new HttpClient();
var userLoginInfo = new LoginData
{
UserName = "TestUser",
UserRole = "TestRole"
};
string api = "https://localhost:7049/api/LoginTest/TestLogin";
var response = await client.PostAsJsonAsync(api, userLoginInfo);
Message = await response.Content.ReadAsStringAsync();
}
public async Task OnPostLogout()
{
var client = new HttpClient();
var userLoginInfo = new LoginData();
string api = "https://localhost:7049/api/LoginTest/TestLogout";
var response = await client.PostAsJsonAsync(api, userLoginInfo);
Message = await response.Content.ReadAsStringAsync();
}
public async Task OnPostValidate()
{
var client = new HttpClient();
var userLoginInfo = new LoginData();
string api = "https://localhost:7049/api/LoginTest/TestVerify";
var response = await client.PostAsJsonAsync(api, userLoginInfo);
int statusCode = ((int)response.StatusCode);
if (response.IsSuccessStatusCode)
Message = await response.Content.ReadAsStringAsync();
else
Message = $"Failed with status code: ({response.StatusCode}/{statusCode})";
}
If I try via the front-end, I click on the Login, and it says it is successfully, but when I click on the Validate, it returns a 404 presumably because it doesn't think it is authorized even though I did a log in (or if I authorize anonymous for the validate, it says no one is logged in). If I do the same calls via Swagger, the login works the same, but the validate remembers the login, which is the desired behavior. Why is the login not being remembered when I call the API via the front-end, but it is when I do it via Swagger? And how can I fix this?
Thanks.
In my application, the user would login into the application and then authorize facebook(by clicking a button in a secure area) to allow the application to get facebook posts etc.
Here's the code that I have written to save the claims and authentication tokens and connect those to the internal user account.
Am I following the right approach? If not, would it be easier to directly insert records into the AspNetUserClaims, AspNetUserTokens tables for claims, authentication tokens, using Entity Framework core.
public async Task<IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (remoteError != null)
{
ErrorMessage = $"Error from external provider: {remoteError}";
return RedirectToPage("./Settings", new { ReturnUrl = returnUrl });
}
// Get the information about the user from the external login provider
var identityUser = await UserManager.GetUserAsync(User);
var externalLoginInfo = await SignInManager.GetExternalLoginInfoAsync();
if (externalLoginInfo == null)
{
ErrorMessage = "Error loading external login information during confirmation.";
return RedirectToPage("./Settings", new { ReturnUrl = returnUrl });
}
var applicationUser = new ApplicationUser { UserName = identityUser.Email, Email = identityUser.Email , SecurityStamp= Guid.NewGuid().ToString()};
var identityResult = await this.UserManager.AddLoginAsync(applicationUser, externalLoginInfo);
if (identityResult.Succeeded)
{
if (externalLoginInfo.Principal.HasClaim(c => c.Type == ClaimTypes.GivenName))
{
await this.UserManager.AddClaimAsync(applicationUser, externalLoginInfo.Principal.FindFirst(ClaimTypes.GivenName));
}
identityResult = await SignInManager.UpdateExternalAuthenticationTokensAsync(externalLoginInfo);
var authenticationProperties = new AuthenticationProperties();
authenticationProperties.StoreTokens(externalLoginInfo.AuthenticationTokens);
//authenticationProperties.IsPersistent = true;
#endregion
return LocalRedirect(returnUrl);
}
foreach (var error in identityResult.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
LoginProvider = externalLoginInfo.LoginProvider;
ReturnUrl = returnUrl;
return Page();
}
#endregion
}
I have tried some authorization examples in asp core 2 wiht jwt tokens and asp core identity. I have followed this code https://github.com/SunilAnthony/SimpleSecureAPI and it works fine.
The problem is role based authorization. I tried something like this:
http://www.jerriepelser.com/blog/using-roles-with-the-jwt-middleware/
and the result is strange.
My controller method:
[HttpGet]
[Authorize]
public IActionResult Get()
{
IEnumerable<Claim> claims = User.Claims; // contains claim with Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" and Value = "Administrator"
bool role = User.IsInRole("Administrator"); // true
bool claim = User.HasClaim(ClaimTypes.Role, "Administrator"); // true
return Ok(claims);
}
When I call this endpoint just with attribute [Authorize] and check role / claims in code for current user it seems good (both checks are true), but when I have changed my authorization attribute to [Authorize(Roles = "Administrator")] it does not work -> when I call this endpoint with this attribute I will receive 404. I don't know where is the problem. My startup class is completely same as in the git link above and I have just added list of string role names in the payload of access_token within then "roles" array:
It is hardcoded but I have changed my login method just for test like this:
[HttpPost("login")]
public async Task<IActionResult> SignIn([FromBody] Credentials Credentials)
{
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(Credentials.Email, Credentials.Password, false, false);
if (result.Succeeded)
{
IdentityUser user = await _userManager.FindByEmailAsync(Credentials.Email);
List<string> roles = new List<string>();
roles.Add("Administrator");
return new JsonResult(new Dictionary<string, object>
{
{ "access_token", GetAccessToken(Credentials.Email, roles) },
{ "username", user.Email },
{ "expired_on", DateTime.UtcNow.AddMinutes(_tokenLength) },
{ "id_token", GetIdToken(user) }
});
}
return new JsonResult("Unable to sign in") { StatusCode = 401 };
}
return new JsonResult("Unable to sign in") { StatusCode = 401 };
}
And the GetAccessTokenMethod:
private string GetAccessToken(string Email, List<string> roles)
{
var payload = new Dictionary<string, object>
{
{ "sub", Email },
{ "email", Email },
{ "roles", roles },
};
return GetToken(payload);
}
Where is the problem with the [Authorize(Roles = "Administrator")] attribute?
The problem is with the claim's type:
http://schemas.microsoft.com/ws/2008/06/identity/claims/role
Somehow, the [Authorize] attribute fails to work when used with Roles value.
So this [Authorize(Roles = "Administartor")] doesn't work.
You have to map the claim type to only role by applying transformation on Startup class.
If you have an Owin based project:
app.UseClaimsTransformation(incoming =>
{
// either add claims to incoming, or create new principal
var appPrincipal = new ClaimsPrincipal(incoming);
if (appPrincipal.HasClaim(x => x.Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"))
{
var value = appPrincipal.Claims.First(x =>
x.Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/role").Value;
incoming.Identities.First().AddClaim(new Claim("role", value));
}
return Task.FromResult(appPrincipal);
});
I'm trying to get user name and user email from facebook. I read a lot of information on this topic and this is my final code that works for some reason only on my facebook app admin account:
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
/*Other external login options*/
var FacebookOptions = new FacebookAuthenticationOptions()
{
AppId = "My App Id",
AppSecret = "My App Secret",
SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie,
BackchannelHttpHandler = new FacebookBackChannelHandler(),
UserInformationEndpoint = "https://graph.facebook.com/v2.7/me?fields=id,name,email"
};
}
}
public class FacebookBackChannelHandler : HttpClientHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (!request.RequestUri.AbsolutePath.Contains("/oauth"))
{
request.RequestUri = new Uri(request.RequestUri.AbsoluteUri.Replace("?access_token", "&access_token"));
}
return await base.SendAsync(request, cancellationToken);
}
}
public class AccountController : Controller
{
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
/*my sign in code that works on my facebook app admin account*/
}
}
On every over account I get loginInfo.Email is equal to null.
In developers.facebook.com I have:
When someone clicks on "Login with Facebook" he gets this message:
If I click "Review the info you provide" i get:
What am I missing? Why doesn't it work?
Finally found an answer! All that needs to be done is to add Scope = { "email" } to FacebookOptions and that's solves the problem!
My code now:
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
/*Other external login options*/
var FacebookOptions = new FacebookAuthenticationOptions()
{
AppId = "My App Id",
AppSecret = "My App Secret",
SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie,
BackchannelHttpHandler = new FacebookBackChannelHandler(),
Scope = { "email" },
UserInformationEndpoint = "https://graph.facebook.com/v2.7/me?fields=id,name,email"
};
}
}
The rest of the code stays the same. I only added error page for the case if this problem returns:
public class AccountController : Controller
{
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if(loginInfo.Email == null)
{
return RedirectToAction("FacebookError", "Account");
}
/*my sign in code*/
}
}
Facebook offers people full control over the permissions they grant to an app. That control extends beyond the point at which they see the login dialog. They can choose not to grant certain permissions during the login process. They can also revoke permissions in their Facebook privacy settings at any time. Apps should check for the validity of permissions before attempting to perform an API call where they are required. For example, checking that email action is still granted before attempting to publish an Open Graph story.
facebook provides the a graph API endpoint to retrieve a list of granted permissions:
GET /{user-id}/permissions
The call must be made with either a user access token or your app access token. The call will return a JSON string containing the permission names which have been granted to the app and their status:
{
"data": [
{
"permission": "public_profile",
"status": "granted"
},
{
"permission": "publish_actions",
"status": "granted"
},
{
"permission": "user_friends",
"status": "declined"
}
]
}
by using this, you can detect whether it is possible or not to fetch the information you want. hope this helps.
reference: https://developers.facebook.com/docs/facebook-login/permissions/requesting-and-revoking
This time I'm triying to set and get the whole information about the user at the FrontSide but I don't know whant i'm doing wrong
I have two separated projects the first one is the Webapi Project and I'm using it to SingIn the user giving then a token.
// GET api/Account/ExternalLogin
[OverrideAuthentication]
[HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]
[AllowAnonymous]
[Route("ExternalLogin", Name = "ExternalLogin")]
public async Task<IHttpActionResult> GetExternalLogin(string provider, string error = null)
{
if (error != null)
return Redirect(Url.Content("~/") + "#error=" + Uri.EscapeDataString(error));
if (!User.Identity.IsAuthenticated)
return new ChallengeResult(provider, this);
ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);
if (externalLogin == null)
return InternalServerError();
if (externalLogin.LoginProvider != provider)
{
Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
return new ChallengeResult(provider, this);
}
AppJobSeeker user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider, externalLogin.ProviderKey));
bool hasRegistered = user != null;
if (hasRegistered)
{
Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
ClaimsIdentity oAuthIdentity = await UserManager.CreateIdentityAsync(user, OAuthDefaults.AuthenticationType);
ClaimsIdentity cookieIdentity = await UserManager.CreateIdentityAsync(user, CookieAuthenticationDefaults.AuthenticationType);
AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName, user.Id);
Authentication.SignIn(properties, oAuthIdentity, cookieIdentity);
}
else
{
IEnumerable<Claim> claims = externalLogin.GetClaims();
ClaimsIdentity identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);
Authentication.SignIn(identity);
}
return Ok();
}
And the client side is a MVC 5 Project where I have one method to postasyn the authentication and another one to Create the AuthTickect like this...
public async Task<T> AuthenticateAsync<T>(string userName, string password)
{
using (var client = new HttpClient())
{
var result = await client.PostAsync((#"http://localhost:8060/Token"), new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>(#"grant_type", #"password"),
new KeyValuePair<string, string>(#"userName", userName),
new KeyValuePair<string, string>(#"password", password)
}));
string json = await result.Content.ReadAsStringAsync();
if (result.IsSuccessStatusCode)
return JsonConvert.DeserializeObject<T>(json);
throw new ApiException(result.StatusCode, json);
}
}
private void CreateTicket(SignInResult result, SignInModel model, string returnUrl)
{
//Let's keep the user authenticated in the MVC webapp.
//By using the AccessToken, we can use User.Identity.Name in the MVC controllers to make API calls.
FormsAuthentication.SetAuthCookie(result.AccessToken, model.RememberMe);
//Create an AuthenticationTicket to generate a cookie used to authenticate against Web API.
//But before we can do that, we need a ClaimsIdentity that can be authenticated in Web API.
Claim[] claims =
{
new Claim(ClaimTypes.Name, result.AccessToken), //Name is the default name claim type, and UserName is the one known also in Web API.
new Claim(ClaimTypes.Email, result.UserName), //If you want to use User.Identity.GetUserId in Web API, you need a NameIdentifier claim.
};
//Generate a new ClaimsIdentity, using the DefaultAuthenticationTypes.ApplicationCookie authenticationType.
//This also matches what we've set up in Web API.
AuthenticationTicket authTicket = new AuthenticationTicket(new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie), new AuthenticationProperties
{
ExpiresUtc = result.Expires,
IsPersistent = model.RememberMe,
IssuedUtc = result.Issued,
RedirectUri = returnUrl,
});
//HttpContext.Response..User = principal;
//And now it's time to generate the cookie data. This is using the same code that is being used by the CookieAuthenticationMiddleware class in OWIN.
byte[] userData = DataSerializers.Ticket.Serialize(authTicket);
//Protect this user data and add the extra properties. These need to be the same as in Web API!
byte[] protectedData = MachineKey.Protect(userData, new[] { "Microsoft.Owin.Security.Cookies.CookieAuthenticationMiddleware", DefaultAuthenticationTypes.ApplicationCookie, "v1" });
//base64-encode this data.
string protectedText = TextEncodings.Base64Url.Encode(protectedData);
//And now, we have the cookie.
Response.SetCookie(new HttpCookie("JobSeekerAuth")
{
HttpOnly = true,
Expires = result.Expires.UtcDateTime,
Value = protectedText,
});
}
And my login method looks like
// POST: Account/SignIn
[HttpPost]
public async Task<ActionResult> Login(SignInModel model, string returnUrl)
{
if (!ModelState.IsValid)
return View(model);
try
{
CreateTicket(await WebApiService.Instance.AuthenticateAsync<SignInResult>(model.Email, model.Password), model, returnUrl);
return RedirectToLocal(returnUrl);
//return await WebApiService.Instance.AuthenticateAsync<SignInResult>(model.Email, model.Password) != null ? RedirectToLocal(returnUrl) : RedirectToLocal(returnUrl);
}
catch (ApiException ex)
{
//No 200 OK result, what went wrong?
HandleBadRequest(ex);
if (!ModelState.IsValid)
return View(model);
throw;
}
}
The problem is I want to use the GenericPrincipal at the Razor View two get the userId or the username fro the logged user and when I trying to doing so It gives me nothing more than the token here
#if (HttpContext.Current.User.Identity.IsAuthenticated)
{
<li>#Html.ActionLink("Sign Out", "SignOut", "Account")</li>
}
else
{...
So, I don't know how to get this goal
Best regards!...
My Authentication Method Works Well because once I go to the login method this one gives me my entity SignInResult wich looks like with all its value setted
[JsonProperty("access_token")]
public string AccessToken { get; set; }
//Included to show all the available properties, but unused in this sample
[JsonProperty("token_type")]
public string TokenType { get; set; }
[JsonProperty("expires_in")]
public uint ExpiresIn { get; set; }
[JsonProperty("userName")]
public string UserName { get; set; }
[JsonProperty(".issued")]
public DateTimeOffset Issued { get; set; }
[JsonProperty(".expires")]
public DateTimeOffset Expires { get; set; }
[JsonProperty("userId")]
public string UserId { get; set; }
I also tried to set to the Thread.CurrentPrincipal but not success
Best Regards