IdentityServer4 requesting a JWT / Access Bearer Token using the password grant in asp.net core - asp.net-core

I've searched all over on requesting a JWT / Access Bearer Token using the password grant using IdentityServer4 in asp.net core, but I cant seem to find the right way to do it.
Below is the POST Request from which I register my user.
http://localhost:52718/account/register
Below is the Bearer Token GET Request from which I can get JWT Token using IdentityServer4
http://localhost:52718/connect/token
Below is the POST Request from which I Login my user
http://localhost:52718/account/signin
Now, what I'm trying to do is when I login my user then I want a JWT / Bearer Token same as I get from here http://localhost:52718/connect/token. When I hit this URL.
Here is my AccountController Code:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Server.Models;
using Server.Models.AccountViewModels;
using Server.Models.UserViewModels;
namespace Server.Controllers
{
public class AccountController : Controller
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
public AccountController(
UserManager<ApplicationUser> userManager,
RoleManager<IdentityRole> roleManager
)
{
_userManager = userManager;
_roleManager = roleManager;
}
[HttpPost]
public async Task<IActionResult> Register([FromBody]RegisterViewModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var user = new ApplicationUser { UserName = model.UserName, FirstName = model.FirstName, LastName = model.LastName, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
string role = "Basic User";
if (result.Succeeded)
{
if (await _roleManager.FindByNameAsync(role) == null)
{
await _roleManager.CreateAsync(new IdentityRole(role));
}
await _userManager.AddToRoleAsync(user, role);
await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("userName", user.UserName));
await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("firstName", user.FirstName));
await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("lastName", user.LastName));
await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("email", user.Email));
await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("role", role));
return Ok(new ProfileViewModel(user));
}
return BadRequest(result.Errors);
}
public async Task<IActionResult> Signin([FromBody]LoginViewModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var result = await _userManager.FindByNameAsync(model.UserName);
if (result != null && await _userManager.CheckPasswordAsync(result, model.Password))
{
return Ok(new ProfileViewModel(result));
}
return BadRequest("Invalid username or password.");
}
}
}
When I hit signin method I successfully get the data of user.
But I also need a jwt / access token when user login my app.
Now my actual question is:
What can I do in my signin method so when user login it returns me token along with other user data. I hope I briefly explain my question.
Thanks

I've found my own question answer. Before starting I show you my that code where I'm Defining the client.
public static IEnumerable<Client> GetClients()
{
// client credentials client
return new List<Client>
{
// resource owner password grant client
new Client
{
ClientId = "ro.angular",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.Address,
"api1"
}
}
};
}
Now what I do in my Signin Method is to use the TokenClient class to request the token. To create an instance you need to pass in the token endpoint address, client id and secret.
Next I'm using Requesting a token using the password grant to allows a client to send username and password to the token service and get an access token back that represents that user.
Here is my Signin Code which I need to modify:
public async Task<IActionResult> Signin([FromBody]LoginViewModel model)
{
var disco = await DiscoveryClient.GetAsync("http://localhost:52718");
if (disco.IsError)
{
return BadRequest(disco.Error);
}
var tokenClient = new TokenClient(disco.TokenEndpoint, "ro.angular", "secret");
var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(model.UserName, model.Password, "api1 openid");
if (tokenResponse.IsError)
{
return BadRequest(tokenResponse.Error);
}
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var user = _userManager.FindByNameAsync(model.UserName);
var result = await _userManager.FindByNameAsync(model.UserName);
if (result != null && await _userManager.CheckPasswordAsync(result, model.Password))
{
return Ok(new ProfileViewModel(result, tokenResponse));
}
return BadRequest("Invalid username or password.");
}
Also I modify ProfileViewModel Class and add two new Token & Expiry:
public class ProfileViewModel
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Token { get; set; }
public int Expiry { get; set; }
public ProfileViewModel()
{
}
public ProfileViewModel(ApplicationUser user, TokenResponse UToken = null)
{
Id = user.Id;
FirstName = user.FirstName;
LastName = user.LastName;
Email = user.Email;
Token = UToken.AccessToken;
Expiry = UToken.ExpiresIn;
}
public static IEnumerable<ProfileViewModel> GetUserProfiles(IEnumerable<ApplicationUser> users)
{
var profiles = new List<ProfileViewModel> { };
foreach (ApplicationUser user in users)
{
profiles.Add(new ProfileViewModel(user));
}
return profiles;
}
}
Now Here is my desire output. Hope this answer help others.

Related

ArgumentNullException: Value cannot be null. (Parameter 'value')

I am having trouble with loging in from postman to my API. I get the roles back no problem but when they are used as parameters in the tokenservice they just stop working I get the following error :
Error
This is my endpoint :
[HttpPost("login")]
public async Task<IActionResult> Login(LoginUser loginData)
{
var userFromDb = await _userManager.FindByNameAsync(loginData.UserName);
if (userFromDb == null) return NotFound();
var result = await _signinManager.CheckPasswordSignInAsync(userFromDb, loginData.Password, false);
if (result == null) return BadRequest("Invalid Password");
var role = await _userManager.GetRolesAsync(userFromDb);
return Ok(
new
{
result = result,
username = userFromDb.UserName,
email = userFromDb.Email,
token = _tokenService.GenerateToken(userFromDb, role)
}
);
}
And this is the Token Service :
public class TokenService : ITokenService
{
private readonly IConfiguration _config;
public TokenService(IConfiguration config)
{
_config = config;
}
public string GenerateToken(IdentityUser user, IList<string> roles)
{
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.GivenName, user.UserName),
new Claim(JwtRegisteredClaimNames.Email, user.Email)
};
if (roles != null)
{
foreach (var role in roles)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}
}
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Token:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.Now.AddDays(7),
SigningCredentials = creds,
Issuer = _config["Token:Issuer"],
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
I have tried to rewrite my code and espacially this part :
if (roles != null)
{
foreach (var role in roles)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}
}
because when I put an entry point in the token service it tells me that role is null
I checked your code on my application, the code works well, check the following screenshot:
The issue might relates the userFromDb, role value or the configuration value, I suggest you could set some break point to check the userFromDb and role value in the Login method and set break point in the TokenService to check whether the token generated success, refer to the following image:
Update:
the LoginUser:
public class LoginUser
{
public string UserName { get; set; }
public string Password { get; set; }
public string EmailAddress { get; set; }
}
For the IdentityUser, I'm using the Asp.net core Identity default IdentityUser model. because in your code, the GenerateToken method also use the IdentityUser Model.
I think you it is because I am using my own user instead of
IdentityUser
You can check the GenerateToken method and check the userFromDb, might the issue relate it, in the GenerateToken method, you might need to change your code to use your custom user model, instead of the IdentityUser model.

How to return a cookie from an ASP.NET Core Auth Cookie in a Controller

I currently have a razor page where I return a cookie and it works great. However, I am developing a SPA which uses VueJS so I have created an API to directly communicate with. I have converted my code from the Razor Page to the controller but I am not sure how I actually return the cookie when the user tries to log in. If there is a match I want it to return the cookie and create the cookie. As of now I get a 400 code as if this request is not working. Any thoughts what could be wrong with this?
public class LoginController : Controller
{
private readonly LoginDBContext _context;
private string connectionString;
public IConfiguration Configuration { get; }
public LoginController(LoginDBContext context, IConfiguration configuration)
{
_context = context;
connectionString = configuration["ConnectionStrings:MMCARMSContext"];
}
// GET: HomeController
public ActionResult Index()
{
return Ok(new { Result = "Test" });
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login([FromForm] string Username, [FromForm] string Password, [FromForm] bool RememberMe)
{
if (!String.IsNullOrEmpty(Username) && !String.IsNullOrEmpty(Password))
{
var users = _context.UsersAccountsTbl
.Where(a => a.Username == Username)
.Select(a => new { a.InternalUserNumber, a.Username, a.Password })
.ToArray();
if (users.Length == 1) //if we have more than 1 result we have security issue so do not allow login
{
var passwordHasher = new PasswordHasher<string>();
//To use you need to has with var hashedPassword = passwordHasher.HashPassword(UserName, Password);
//System.Diagnostics.Debug.WriteLine(passwordHasher.HashPassword("Username", "password"));
var user = users.First();
if (passwordHasher.VerifyHashedPassword(user.Username, user.Password, Password) == PasswordVerificationResult.Success)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.InternalUserNumber.ToString())
};
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
if (RememberMe)
{
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
new AuthenticationProperties
{
IsPersistent = RememberMe,
ExpiresUtc = DateTimeOffset.UtcNow.AddHours(2)
});
}
else
{
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity));
}
return Ok(new { Result = "Cookie has been created!" });
}
else
{
return Ok(new { Result = "Password is incorrect!" });
}
}
return Ok(new { Result = "Username or Password does not exist!" });
}
else
{
return Ok(new { Result = "Username or Password invalid!" });
}
}
}
You could set the cookie in the HttpResponse, this way the cookie gets added when the client receives the response from your controller:
HttpCookie MyCookie = new HttpCookie("LastVisit");
DateTime now = DateTime.Now;
MyCookie.Value = now.ToString();
MyCookie.Expires = now.AddHours(1);
Response.Cookies.Add(MyCookie);
https://learn.microsoft.com/en-us/dotnet/api/system.web.httpresponse.cookies?view=netframework-4.8

Getting " InvalidOperationException: Error while validating the service descriptor 'ServiceType: MediatR.IRequestHandler`2"

I'm trying to implement refresh token in my api. The api is following CQRS+MediatR pattern and is using JWT for authentication.
After adding a Handler to manage refresh call and a refresh token service I am getting the following error:
Inner Exception 1:
InvalidOperationException: Error while validating the service descriptor 'ServiceType: MediatR.IRequestHandler`2
[UM.Business.Application.Token.Command.Update.UpdateTokenCommand,UM.Business.Application.Common.HandlerResult]
Lifetime: Transient ImplementationType: UM.Business.Application.Token.Command.Update.UpdateTokenHandler':
Unable to resolve service for type 'UM.Infrastructure.Common.Configuration.AuthSettings'
while attempting to activate 'UM.Business.Application.Token.Command.Update.UpdateTokenHandler'.
Inner Exception 2:
InvalidOperationException: Unable to resolve service for type 'UM.Infrastructure.Common.Configuration.AuthSettings'
while attempting to activate 'UM.Business.Application.Token.Command.Update.UpdateTokenHandler'.
My service is doing basic crud operations on the Refresh Token class.
First of all I added dependancy injection in a service module class,
service.AddTransient<IRefreshTokenService, RefreshTokenService>();
This is my controller end point,
[Route("refresh")]
[ProducesResponseType(typeof(LoginResponse), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(IEnumerable<string>), StatusCodes.Status412PreconditionFailed)]
[ProducesResponseType(typeof(string), StatusCodes.Status401Unauthorized)]
[ProducesResponseType(typeof(ConfirmEmail), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(AccountBlocked), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> Refresh([FromBody] UpdateRefreshTokenVM request, CancellationToken ct)
{
var refreshCommand= _mapper.Map<UpdateTokenCommand>(request);
var authenticationResult = await _mediator.Send(refreshCommand, ct);
if (authenticationResult == null)
return Unauthorized();
if (authenticationResult.IsSuccess)
return Ok(authenticationResult.Result);
}
My UpdateRefreshTokenVM,
public class UpdateRefreshTokenVM
{
public string AccessToken { get; set; }
public Core.Domain.Models.RefreshToken RefreshToken { get; set; } }
And UpdateTokenCommand,
public class UpdateTokenCommand : CommandBase<HandlerResult>
{
public string AccessToken { get; set; }
public Core.Domain.Models.RefreshToken RefreshToken { get; set; }
}
Handler getting called is this one,
public UpdateTokenHandler(IUserService userService, IMapper mapper, IRefreshTokenService refreshTokenService, IRoleService roleService, AuthSettings authSetting, IUserClaimsService userClaimService)
{
_userService = userService;
_refreshTokenService = refreshTokenService;
_userClaimService = userClaimService;
_roleService = roleService;
_authSetting = authSetting;
_mapper = mapper;
}
public async Task<HandlerResult> Handle(UpdateTokenCommand request, CancellationToken cancellationToken)
{
var loginResponse = new HandlerResult();
var userIdentity = await _userService.FindByEmailAsync(request.RefreshToken.User.Email);
string accessToken = request.AccessToken;
var refreshToken = request.RefreshToken;
var principal = TokenGenerator.GetPrincipalFromExpiredToken(accessToken);
var username = principal.Identity.Name; //this is mapped to the Name claim by default
var refreshTokenFromDb =await _refreshTokenService.FindByUserId(refreshToken.User.Id);
if (refreshTokenFromDb.RefreshTokenExpiryTime <= DateTime.Now)
{
return null;
}
if (refreshTokenFromDb == null || refreshTokenFromDb != refreshToken )
{
loginResponse.IsSuccess = false;
loginResponse.ErrorMessage="Invalid client request";
loginResponse.Result = null;
return loginResponse;
}
var userClaims = await _userClaimService.GetClaims(userIdentity);
var userRoles = await _roleService.GetUserRoles(userIdentity);
var resultObject = TokenGenerator.GenerateJsonWebToken(userIdentity, userClaims, _authSetting, userRoles);
//var newRefreshToken = TokenGenerator.GenerateRefreshToken();
loginResponse.Result = resultObject;
loginResponse.ErrorMessage = null;
loginResponse.IsSuccess = true;
//user.RefreshToken = newRefreshToken;
//userContext.SaveChanges();
// now save the token variable in db
await _refreshTokenService.UpdateAsync(resultObject.RefreshToken);
return loginResponse;
}
}
Following is the token generator used in the handler,
internal static LoginResponse GenerateJsonWebToken(UM.Core.Domain.Models.User userInfo,IList<System.Security.Claims.Claim> userClaims, AuthSettings authSetting, IList<string> roleNames)
{
userClaims.Add(new System.Security.Claims.Claim(ClaimTypes.Email, userInfo.Email));
userClaims.Add(new System.Security.Claims.Claim(ClaimTypes.NameIdentifier, userInfo.Id));
userClaims.Add(new System.Security.Claims.Claim(ClaimTypes.Name, userInfo.NormalizedUserName));
foreach(string name in roleNames)
{
userClaims.Add(new System.Security.Claims.Claim(ClaimTypes.Role, name));
}
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authSetting.Key));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);
var tokenDescriptor = new SecurityTokenDescriptor()
{
Issuer = authSetting.Issuer,
Audience = authSetting.Audience,
Subject = new ClaimsIdentity(userClaims),
Expires = DateTime.UtcNow.AddMinutes(authSetting.ExpirationTimeInMin),
SigningCredentials = credentials
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
// Now generate refresh token
var refreshToken = new RefreshToken
{
User = userInfo,
//UserId = int.Parse(userInfo.Id),
RefreshTokenString = GenerateRefreshToken(),
RefreshTokenExpiryTime = DateTime.Now.AddDays(14) // will change this later
};
var authenticationResponse = new LoginResponse
{
AccessToken = tokenHandler.WriteToken(token),
RefreshToken = refreshToken,
IsValid = true
};
return authenticationResponse;
}
public static string GenerateRefreshToken()
{
var randomNumber = new byte[32];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(randomNumber);
return Convert.ToBase64String(randomNumber);
}
}
public static ClaimsPrincipal GetPrincipalFromExpiredToken(string token)
{
var tokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false, //you might want to validate the audience and issuer depending on your use case
ValidateIssuer = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("superSecretKey#345")),
ValidateLifetime = false //here we are saying that we don't care about the token's expiration date
};
var tokenHandler = new JwtSecurityTokenHandler();
SecurityToken securityToken;
var principal = tokenHandler.ValidateToken(token, tokenValidationParameters, out securityToken);
var jwtSecurityToken = securityToken as JwtSecurityToken;
if (jwtSecurityToken == null || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
throw new SecurityTokenException("Invalid token");
return principal;
}
Auth settings(which I didn't touch for this implementation)
public class AuthSettings
{
public string Key { get; set; }
public string Issuer { get; set; }
public string Audience { get; set; }
public int ExpirationTimeInMin { get; set; }
}
And my login Response class,
public class LoginResponse
{
public string AccessToken { get; set; }
public RefreshToken RefreshToken { get; set; }
public bool IsValid { get; set; }
public bool VerificationRequired { get; set; }
public bool TwoFactorRequired { get; set; }
public LoginResponse()
{
RefreshToken = new RefreshToken();
}
}

DOTNET CORE JWT Error converting value \"Username\" to type 'jwt_example.Model.LoginModel ERROR

I'm trying to write an API with dotnet core 3.1 + JWT.
I created LoginModel and authController when I try to get a token
postman says to me:
"Error converting value \"Username\" to type 'jwt_example.Model.LoginModel"
That is my authController code :
public class AuthController : ControllerBase
{
private UserManager<ApplicationUser> userManger;
public AuthController(UserManager<ApplicationUser> userManger)
{
this.userManger = userManger;
}
[HttpPost]
[Route("login")]
public async Task<IActionResult> Login([FromBody] LoginModel model)
{
var user = await userManger.FindByNameAsync((model.Username).ToString());
//var user = await
if (user != null && await userManger.CheckPasswordAsync(user, model.Password))
{
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var signinKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("ŞanlıFenerbahçe."));
JwtSecurityToken token = new JwtSecurityToken
(
issuer: "https://localhost:5001",
audience: "https://localhost:5001",
claims: claims,
signingCredentials: new SigningCredentials(signinKey, SecurityAlgorithms.HmacSha256),
expires: DateTime.Now.AddHours(1)
);
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo
});
}
else
{
return BadRequest(new
{
message = "Kullanıcı adı veya şifre hatalı!"
});
}
}
}
And, that is loginModel.cs:
public class LoginModel
{
[Required(ErrorMessage = "Kullanıcı adı boş geçilemez.")]
public string Username { get; set; }
[Required(ErrorMessage = "Parola boş geçilemez.")]
public string Password { get; set; }
}

WebAPI : How to add the Account / Authentication logic to a self hosted WebAPI service

I just came across a great reference example of using authenticated WebAPI with AngularJS:
http://www.codeproject.com/Articles/742532/Using-Web-API-Individual-User-Account-plus-CORS-En?msg=4841205#xx4841205xx
An ideal solution for me would be to have such WebAPI service self hosted instead of running it as a Web application.
I just do not know where to place all of the authentication / authorization logic within a self hosted (OWIN / Topshelf) solution.
For example, in the Web app, we have these two files: Startup.Auth, and ApplicationOAuthProvider:
Startup.Auth:
public partial class Startup
{
static Startup()
{
PublicClientId = "self";
UserManagerFactory = () => new UserManager<IdentityUser>(new UserStore<IdentityUser>());
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true
};
}
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
public static Func<UserManager<IdentityUser>> UserManagerFactory { get; set; }
public static string PublicClientId { get; private set; }
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
}
}
ApplicationOAuthProvider:
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
private readonly string _publicClientId;
private readonly Func<UserManager<IdentityUser>> _userManagerFactory;
public ApplicationOAuthProvider(string publicClientId, Func<UserManager<IdentityUser>> userManagerFactory)
{
if (publicClientId == null)
{
throw new ArgumentNullException("publicClientId");
}
if (userManagerFactory == null)
{
throw new ArgumentNullException("userManagerFactory");
}
_publicClientId = publicClientId;
_userManagerFactory = userManagerFactory;
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
// Add Access-Control-Allow-Origin header as Enabling the Web API CORS will not enable it for this provider request.
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
using (UserManager<IdentityUser> userManager = _userManagerFactory())
{
IdentityUser 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 userManager.CreateIdentityAsync(user,
context.Options.AuthenticationType);
ClaimsIdentity cookiesIdentity = await userManager.CreateIdentityAsync(user,
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);
}
return Task.FromResult<object>(null);
}
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
// Resource 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);
}
public static AuthenticationProperties CreateProperties(string userName)
{
IDictionary<string, string> data = new Dictionary<string, string>
{
{ "userName", userName }
};
return new AuthenticationProperties(data);
}
}
I'm looking for a way to integrate these into my OWIN self hosted app, and have these authentication features. start upon application startup, and function as they do in the Web app version.