I created a application using ASP.NET with EF. I did the login function and when the user logged redirect to WelcomePage. The login was succeeded and redirect to the page but in the page I have the user authenticated.
I put this to see and its false
<p>#User.Identity.IsAuthenticated</p>
I'm just having trouble understanding how to authenticate them. I try to clean cache but thats not the problem.
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
string Con = ConUri();
services.AddDbContext<SysContext>(options =>
{
options.UseNpgsql(Con);
});
services.AddIdentity<User, IdentityRole<Guid>>()
.AddEntityFrameworkStores<SysContext>()
.AddDefaultTokenProviders();
services.AddControllersWithViews().AddRazorRuntimeCompilation();
services.AddControllersWithViews().AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromDays(30);
options.Cookie.HttpOnly = true;
});
services.ConfigureApplicationCookie(options =>
{
options.AccessDeniedPath = new PathString("/Login");
options.LoginPath = new PathString("/Login");
});
}
HomeController.cs
public object Login(String Username, String Password)
{
try
{
if (ModelState.IsValid)
{
var user = _userManager.FindByEmailAsync(Username).Result;
if (user == null)
throw new Exception("Error 1");
var result = _signInManager.CheckPasswordSignInAsync(user,
Password, lockoutOnFailure: false).Result;
if (result.IsLockedOut)
throw new Exception("Error 2");
if (!result.Succeeded)
throw new Exception("Error 3");
var response = _signInManager.PasswordSignInAsync(Username, Password, true, lockoutOnFailure: false).Result;
if (result.Succeeded)
{
var location = new Uri($"{Request.Scheme}://{Request.Host}/WelcomePage");
Response.Cookies.Append("_UserId", user.Id.ToString());
HttpContext.Session.SetString("_User" + user.Id, string.Empty);
return new
{
Sucesso = true,
Url = location
};
}
else
{
throw new Exception("Error ex");
}
}
throw new Exception("Error 4");
}
catch (Exception ex)
{
return new
{
Sucesso = false,
Mensagem = ex.Message
};
}
}
}
You could check the EmailConfirmed Colum if it has a value in your database,if you did not set to send you a confirmed e-mail when you sign up,try to set as below to avoid varify the e-mail:
services.Configure<IdentityOptions>(options =>
{
.......
options.SignIn.RequireConfirmedAccount=false ;
......
})
Why you passed the username as an e-mail address?
var user = _userManager.FindByEmailAsync(Username).Result;
Related
I am integrating the asp.net webforms project with single sign on(SSO) using Openidconnect and Cookie Authentication using Owin libraries. Once authenticated, the cookie should be active for the day and on browser close need to reauthenticate again(which sets up the cookie again).
After certain hours of inactivity it shows user is authenticated, but the ClaimsIdentity is lost. So the app does not work. I need to able to get the name/email address from the Claims.
How can I fix this?
Startup.cs
public void ConfigureAuth(IAppBuilder app)
{
try
{
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.SetDefaultSignInAsAuthenticationType("Identity.Application");
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Identity.Application",
ExpireTimeSpan = 1440,//min
CookieName = "ABC",
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = _clientId,
Authority = _authority,
RedirectUri = _redirectUri,
ResponseType = "code",
Scope = "openid",
SignInAsAuthenticationType = "Identity.Application",
RedeemCode = true,
SaveTokens = true,
ClientSecret = _clientSecret,
Notifications = new OpenIdConnectAuthenticationNotifications()
{
AuthenticationFailed = (context) =>
{
return Task.FromResult(0);
},
AuthorizationCodeReceived = (context) =>
{
Console.WriteLine("ConfigureAuth: AuthorizationCodeReceived");
return Task.FromResult(0);
},
MessageReceived = (context) =>
{
Console.WriteLine("ConfigureAuth: MessageReceived");
return Task.FromResult(0);
},
RedirectToIdentityProvider = (context) =>
{
Console.WriteLine("ConfigureAuth: RedirectToIdentityProvider");
return Task.FromResult(0);
},
SecurityTokenReceived = (context) =>
{
Console.WriteLine("ConfigureAuth: SecurityTokenReceived");
return Task.FromResult(0);
},
SecurityTokenValidated = (context) =>
{
Console.WriteLine("ConfigureAuth: SecurityTokenValidated");
return Task.FromResult(0);
}
}
});
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex.ToString());
}
}
Web.config
<authentication mode="Forms">
<forms loginUrl="AuthenticationHandler.ashx" name=".ASPNETAUTH" protection="None" path="/Default3.aspx" timeout="420" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
<sessionState timeout="420" />
AuthenticationHandler
public class AuthenticationHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
if (!context.Request.IsSecureConnection)
{
string absoluteUri = context.Request.Url.AbsoluteUri;
context.Response.Redirect(absoluteUri.Replace("http://", "https://"), true);
}
if (context.Request.IsAuthenticated)
{
string userName = String.Empty;
var claimsIdentity = context.User.Identity as ClaimsIdentity;
foreach (var claim in claimsIdentity.Claims)
{
if (claim.Type == "name")
{
userName = claim.Value;
break;
}
}
// Redirect back to original URL.
string redirectUrl = FormsAuthentication.GetRedirectUrl(userName, true);
if (!redirectUrl.Contains("default.aspx"))
{
context.Response.Redirect(redirectUrl);
}
}
else
{
ChallengeAuthentication(context);
}
if (!String.IsNullOrEmpty(context.Request.QueryString["signout"]))
{
context.Request.GetOwinContext()
.Authentication
.SignOut(HttpContext.Current.Request.GetOwinContext()
.Authentication.GetAuthenticationTypes()
.Select(o => o.AuthenticationType).ToArray());
}
}
private static void ChallengeAuthentication(HttpContext context)
{
try
{
HttpContext.Current.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties { RedirectUri = context.Request.RawUrl },
OpenIdConnectAuthenticationDefaults.AuthenticationType);
var claimsIdentity = context.User.Identity as ClaimsIdentity;
string userName = string.Empty;
foreach (var claim in claimsIdentity.Claims)
{
string claimType = claim.Type.Replace("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/", "");
string claimValue = claim.Value;
sbMessage.Append(claimType + " = " + claimValue + "<br/>");
if (claimType == "emailaddress")
{
userName = claimValue;
}
}
context.Response.Write(sbMessage.ToString());
string userData = "";
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
userName,
DateTime.Now,
1440,
true,
userData,
FormsAuthentication.FormsCookiePath);
// Encrypt the ticket.
string encTicket = FormsAuthentication.Encrypt(ticket);
// Create the cookie.
context.Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
}
catch (Exception ex)
{
Console.WriteLine("exception authenticating: " + ex.ToString());
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
Default3.aspx.cs
string userName = String.Empty;
var claimsIdentity = User.Identity as ClaimsIdentity;
foreach (var claim in claimsIdentity.Claims)
{
// WEC:: might need a more bulletproof check here.
string claimType = claim.Type.Replace("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/", "");
string claimValue = claim.Value;
if (claimType == "emailaddress")
{
userName = claimValue;//NO VALUE after certain hours of inactivity
}
}
I want to return 500 status code for try catch blocks.
but always returning 400 status codes.
If e mail and password is wrong, I would like to show 400 status code and if error 500 status code.
here my codes. please help me.
public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
return Task.Factory.StartNew(() =>
{
try
{
context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "http://localhost:36725" });
string usertype = context.OwinContext.Get<string>("usertype");
if (usertype == "Profile")
{
var username = context.UserName;
var password = context.Password;
var profiles = new Profiles();
Profile profile = profiles.Login(username, password);
if (profile != null)
{
var claims = new List<Claim>()
{
new Claim("ID", profile.ID.ToString()),
new Claim(ClaimTypes.Name, profile.Name),
new Claim(ClaimTypes.Surname, profile.Surname),
new Claim("ProfilePhotoUrl", profile.ProfilePhotoUrl),
new Claim("UserName", profile.UserName),
new Claim(ClaimTypes.Role, profile.UserType.Name),
new Claim("Language", profile.Language.Name)
};
ClaimsIdentity oAutIdentity = new ClaimsIdentity(claims, Startup.OAuthOptions.AuthenticationType);
context.Validated(new AuthenticationTicket(oAutIdentity, new AuthenticationProperties() { }));
}
else
{
context.SetError("invalid_grant", "The e-mail or password is incorrect");
}
}
else if (usertype == "Page")
{
var username = context.UserName;
var password = context.Password;
var pages = new Pages();
Page page = pages.Login(username, password);
if (page != null)
{
var claims = new List<Claim>()
{
new Claim("ID", page .ID.ToString()),
new Claim(ClaimTypes.Name, page.Name),
new Claim("ProfilePhotoUrl", page.ProfilePhotoUrl),
new Claim("UserName", page.UserName),
new Claim(ClaimTypes.Role, page.UserType.Name)
};
ClaimsIdentity oAutIdentity = new ClaimsIdentity(claims, Startup.OAuthOptions.AuthenticationType);
context.Validated(new AuthenticationTicket(oAutIdentity, new AuthenticationProperties() { }));
}
else
{
context.SetError("invalid_grant", "The e-mail or password is incorrect");
}
}
else if (usertype == "Anonymous")
{
var username = context.UserName;
var password = context.Password;
string name = context.OwinContext.Get<string>("name");
string surname = context.OwinContext.Get<string>("surname");
var profiles = new Profiles();
Profile profile = profiles.Login(name, surname, username, password);
if (profile != null)
{
var claims = new List<Claim>()
{
new Claim("ID", profile.ID.ToString()),
new Claim(ClaimTypes.Name, profile.Name),
new Claim(ClaimTypes.Surname, profile.Surname),
new Claim(ClaimTypes.Email, profile.Email),
new Claim(ClaimTypes.Role, profile.UserType.Name),
};
ClaimsIdentity oAutIdentity = new ClaimsIdentity(claims, Startup.OAuthOptions.AuthenticationType);
context.Validated(new AuthenticationTicket(oAutIdentity, new AuthenticationProperties() { }));
}
else
{
Http.Log log = new Http.Log("An unknown error occurred");
context.SetError("invalid_grant", "An unknown error occurred");
}
}
else
{
Http.Log log = new Http.Log("User Type is incorrect");
context.SetError("invalid_grant", "User Type is incorrect");
}
}
catch (Exception ex)
{
Http.Log log = new Http.Log(ex.Message + " " + "An unknown error occurred");
context.SetError("invalid_grant", "An unknown error occurred");
}
});
}
This can be achieved by throwing a HttpResponseException with the appropriate HttpStatusCode:
if (EmailAndOrPasswordIsWrong)
{
throw new HttpResponseException(HttpStatusCode.BadRequest); // 400
}
if (SomethingElseGoesWrong)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError); // 500
}
I trying impliment Active Directory authentication for my ASP.NET MVC application. I use System.DirectoryServices and during login find user in UserManager. If user not found I'm trying find user in Active Directory and if successful register user in asp.net mvc app with UserManager.CreateAsync().
private ApplicationUserManager _userManager;
private ApplicationRoleManager _roleManager;
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel loginModel, string returnUrl)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindAsync(loginModel.UserName, loginModel.Password);
if (user != null)
{
await SignInAsync(user, loginModel.RememberMe);
return RedirectToLocal(returnUrl);
}
string userFullName;
if (AuthenticateActiveDirectoryUser("mydomain.local", loginModel.UserName, loginModel.Password, out userFullName))
{
var newUser = new ApplicationUser { UserName = loginModel.UserName, FullName = userFullName };
var result = await UserManager.CreateAsync(newUser, loginModel.Password);
if (result.Succeeded)
{
await SignInAsync(newUser, loginModel.RememberMe);
return RedirectToLocal(returnUrl);
}
AddErrors(result);
}
else
{
ModelState.AddModelError("", "Invalid UserName or Password");
}
}
return View(loginModel);
}
private bool AuthenticateActiveDirectoryUser(
string domain,
string username,
string password,
out string fullName)
{
fullName = string.Empty;
var domainAndUsername = string.Format("{0}\\{1}", domain, username);
var ldapPath = "";
var entry = new DirectoryEntry(ldapPath, domainAndUsername, password);
try
{
// Bind to the native AdsObject to force authentication.
var obj = entry.NativeObject;
var search = new DirectorySearcher(entry) { Filter = "(SAMAccountName=" + username + ")" };
search.PropertiesToLoad.Add("cn");
var result = search.FindOne();
if (result == null)
return false;
try
{
fullName = (string)result.Properties["cn"][0];
}
catch
{
fullName = string.Empty;
}
}
catch (Exception ex)
{
return false;
}
return true;
}
But in my implementation ignored cases if user change password in Active Directory account or AD Account was deleted.
I can check it manually in my code, but maybe exists other ways in ASP.NET Identity to implement authentication by Active Directory user account?
see if this can help u
protected bool ActiveDirectoryLogin(string Username, string Password, string Domain)
{
bool Success = false;
//System.DirectoryServices.DirectoryEntry Entry =
// new System.DirectoryServices.DirectoryEntry("LDAP://***.**.**.**:389/cn=***-People,o=**,dc=**,dc=edu,dc=sa", "uid=" + Username + ",cn=***-People,o=***,dc=***,dc=edu,dc=sa", Password, AuthenticationTypes.None);
System.DirectoryServices.DirectoryEntry Entry =
new System.DirectoryServices.DirectoryEntry("LDAP://ldapmaster.***.edu.sa:389/cn=***-People,o=***,dc=***,dc=edu,dc=sa", "uid=" + Username + ",cn=***-People,o=***,dc=***,dc=edu,dc=sa", Password,AuthenticationTypes.None);
//System.DirectoryServices.DirectoryEntry Entry =
// new System.DirectoryServices.DirectoryEntry("LDAP://ldapmaster.***.edu.sa:389/cn=***-People,o=***,dc=***,dc=edu,dc=sa", Username , Password, AuthenticationTypes.None);
System.DirectoryServices.DirectorySearcher Searcher = new System.DirectoryServices.DirectorySearcher(Entry);
try
{
Object nat = Entry.NativeObject;
Success = true;
// System.DirectoryServices.SearchResult Results = Searcher.FindOne();
// Success = (Results != null);
}
catch (Exception e)
{
Success = false;
}
return Success;
}
I'm adding confirmation email feature to my ASP.NET WebAPI project. The server can send email fine, however, the confirmation link always return "Invalid token".
I checked some reasons as pointed out here
http://tech.trailmax.info/2015/05/asp-net-identity-invalid-token-for-password-reset-or-email-confirmation/
but it seems that none of them is the root cause
Below is my code:
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
IdentityResult result;
result = await UserManager.CreateAsync(user, model.Password);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
try
{
await userManager.AddToRoleAsync(user.Id, "Player");
//Generate email confirmation token
//var provider = new DpapiDataProtectionProvider("GSEP");
var provider = new MachineKeyProtectionProvider();
userManager.UserTokenProvider = new DataProtectorTokenProvider<GSEPUser>(provider.Create("EmailConfirmation"));
var code = await userManager.GenerateEmailConfirmationTokenAsync(user.Id);
code = System.Web.HttpUtility.UrlEncode(code);
EmailHelper emailHelper = new EmailHelper();
string callBackUrl = emailHelper.GetCallBackUrl(user, code);
EmailMessage message = new EmailMessage();
message.Body = callBackUrl;
message.Destination = user.Email;
message.Subject = "GSEP Account confirmation";
emailHelper.sendMail(message);
}
catch (Exception e)
{
return Ok(GSEPWebAPI.App_Start.Constants.ErrorException(e));
}
}
And now is EmailHelper
public class EmailHelper
{
public string GetCallBackUrl(GSEPUser user, string code)
{
var newRouteValues = new RouteValueDictionary(new { userId = user.Id, code = code });
newRouteValues.Add("httproute", true);
UrlHelper urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext, RouteTable.Routes);
string callbackUrl = urlHelper.Action(
"ConfirmEmail",
"Account",
newRouteValues,
HttpContext.Current.Request.Url.Scheme
);
return callbackUrl;
}
public void sendMail(EmailMessage message)
{
#region formatter
string text = string.Format("Please click on this link to {0}: {1}", message.Subject, message.Body);
string html = "Please confirm your account by clicking this link: link<br/>";
html += HttpUtility.HtmlEncode(#"Or click on the copy the following link on the browser:" + message.Body);
#endregion
MailMessage msg = new MailMessage();
msg.From = new MailAddress("myemail#example.com");
msg.To.Add(new MailAddress(message.Destination));
msg.Subject = message.Subject;
msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(text, null, MediaTypeNames.Text.Plain));
msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(html, null, MediaTypeNames.Text.Html));
SmtpClient smtpClient = new SmtpClient("smtp-mail.outlook.com", Convert.ToInt32(587));
System.Net.NetworkCredential credentials = new System.Net.NetworkCredential("myemail#example.com", "mypassword!");
smtpClient.Credentials = credentials;
smtpClient.EnableSsl = true;
smtpClient.Send(msg);
}
}
And 2 MachineKey class
public class MachineKeyProtectionProvider : IDataProtectionProvider
{
public IDataProtector Create(params string[] purposes)
{
return new MachineKeyDataProtector(purposes);
}
}
public class MachineKeyDataProtector : IDataProtector
{
private readonly string[] _purposes;
public MachineKeyDataProtector(string[] purposes)
{
_purposes = purposes;
}
public byte[] Protect(byte[] userData)
{
return MachineKey.Protect(userData, _purposes);
}
public byte[] Unprotect(byte[] protectedData)
{
return MachineKey.Unprotect(protectedData, _purposes);
}
}
I also added machineKey tag in Web.config as some instruction pointed out.
And finally is my confirmation email API
[AllowAnonymous]
[HttpGet]
public async Task<IHttpActionResult> ConfirmEmail(string userId, string code)
{
if (userId == null || code == null)
{
return Ok("Confirm error");
}
IdentityResult result;
try
{
result = await UserManager.ConfirmEmailAsync(userId, code);
}
catch (InvalidOperationException ioe)
{
// ConfirmEmailAsync throws when the userId is not found.
return Ok("UserID not found");
}
if (result.Succeeded)
{
return Ok("Confirmation succesfully");
}
else
{
return Ok(result.Errors);
}
}
Please show me where am I go wrong
I know this is an old thread. But I though of adding the answer as it could help others.
You are using the below code
string callbackUrl = urlHelper.Action(
"ConfirmEmail",
"Account",
newRouteValues,
HttpContext.Current.Request.Url.Scheme
);
and the UrlHelper.Action already does the url encoding for you in the latest MVC versions. So here in your code you are doing the encoding twice (one inside the Register and another inside GetCallBackUrl using urlHelper.Action) and that is why you are getting the invalid token error.
I'm using the new Microsoft identity to manage my website login and register.
I've configured the website to start using external login (Facebook).
How i can get the Access Token in the (RegisterExternalLogin) page?
``
protected void Page_Load(){
// Process the result from an auth provider in the request
ProviderName = IdentityHelper.GetProviderNameFromRequest(Request);
if (String.IsNullOrEmpty(ProviderName))
{
RedirectOnFail();
return;
}
if (!IsPostBack)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var loginInfo = Context.GetOwinContext().Authentication.GetExternalLoginInfo();
if (loginInfo == null)
{
RedirectOnFail();
return;
}
var user = manager.Find(loginInfo.Login);
if (user != null)
{
IdentityHelper.SignIn(manager, user, isPersistent: false);
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
}
else if (User.Identity.IsAuthenticated)
{
Response.Write("ok.2");
// Apply Xsrf check when linking
var verifiedloginInfo = Context.GetOwinContext().Authentication.GetExternalLoginInfo(IdentityHelper.XsrfKey, User.Identity.GetUserId());
if (verifiedloginInfo == null)
{
RedirectOnFail();
return;
}
var result = manager.AddLogin(User.Identity.GetUserId(), verifiedloginInfo.Login);
if (result.Succeeded)
{
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
}
else
{
AddErrors(result);
return;
}
}
else
{
try
{
var accessToken = "What can i get the access token";
Response.Write(accessToken + "<br>");
var client = new FacebookClient(accessToken);
//var client = new FacebookClient();
dynamic me = client.Get("me");
string firstName = me.first_name;
string lastName = me.last_name;
Response.Write(firstName + " " + lastName);
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
email.Text = loginInfo.Email;
}
}
}
Regards,
Moayyad