Asp.net Identity Email Verifcation Token Not Recognized - asp.net

We are using Microsoft's Identity Framework v2.0 in a web forms application. All is working well. We decided we want to add email verification as part of the new account set up process. If we validate the token after it is created in the same page, we are successful. But if we try to validate the token in a different page, it fails. The process is very simple:
Admin creates a new account by providing user's email and name. (we do not support self registration).
User clicks link he gets in email to validate the email was received.
Here is the code to create the email verification token:
var manager = new UserManager();
var user = new ApplicationUser() { UserName = EmailAddress.Text, Email = EmailAddress.Text, FirstName = FirstName.Text, LastName = LastName.Text };
IdentityResult result = manager.Create(user);
var provider = new DpapiDataProtectionProvider();
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("EmailConfirmation"))
{
TokenLifespan = TimeSpan.FromHours(24)
};
var strToken = manager.GenerateEmailConfirmationToken(user.Id);
//IdentityResult validToken = manager.ConfirmEmail(user.Id, strToken);
strToken = HttpUtility.UrlEncode(strToken.ToString());
NOTE: If we uncomment the line beginning //IdentityResult validToken..., then it succeeds.
Here is the code on the VerifyEmail page:
string userid = Request.QueryString["id"].ToString();
string tokenReceived = Request.QueryString["token"].ToString();
//tokenReceived = HttpUtility.UrlDecode(tokenReceived);
ApplicationUser User = new ApplicationUser();
var manager = new UserManager();
User = manager.FindById(userid);
var provider = new DpapiDataProtectionProvider();
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("EmailConfirmation"))
{
TokenLifespan = TimeSpan.FromHours(24)
};
IdentityResult validToken = manager.ConfirmEmail(User.Id, tokenReceived);
The validToken line does not succeed in this file. I have validated that the strings User.Id and tokenReceived match EXACTLY in both file, so there is no URL corruption going on. (That is why I commented out the UrlDecode since it seems to be decoded by the browser automatically - when I try to decode, it is not 100% the same as the string before encoding).
So I am certain we are calling the same method (ConfirmEmail) and that the two parameters that are passed are exactly the same strings. I am also aware that a token can only be validated once, so I am not trying to re-use them after once validating them.
Any ideas would be welcome.

I think the problem in DpapiDataProtectionProvider - If you use the same instance of this class in creating and validating the token, it'll work fine.
Any reason you are not getting UserManager from Owin Context as per VC2013 template?

Related

Retrieve logged user info from microsoft graph in a framework .net environment

I need to implement SSO in a .net framework web application environment. Need to authenticate and retrieve the samaccountname of the logged user.
I have a working code, but only works on a Desktop and mobile device environments, I guess because I’m using "PublicClientApplicationBuilder".
Sample working code for desktop:
string clientId = "c8a73432-9383-4e7c.....";
string tenantId = "efe4a126-2f4f-42ef.....";
var app = PublicClientApplicationBuilder.Create(clientId)
.WithTenantId(tenantId)
.WithRedirectUri(http://localhost)
.Build();
string[] scopes = new string[]
{
https://graph.microsoft.com/User.Read
};
var result = await app.AcquireTokenInteractive(scopes)
.ExecuteAsync();
var stream = result.IdToken.ToString(); // return IDtoken with samaccountname
Does anybody have a sample code working for a web app?
I have tried with "ConfidentialClientApplicationBuilder", but doesn’t work:
string clientId = "c8a73432-9383...";
string tenantId = "efe4a126-2f4f...";
string secret = "1qN8Q~4m7qD5_...";
string authorityUri = $https://login.microsoftonline.com/efe4e126-2f4f-42ef...;
var app = ConfidentialClientApplicationBuilder.Create(clientId)
.WithClientSecret(secret)
.WithAuthority(new Uri(authorityUri))
.WithRedirectUri(http://localhost)
.Build();
string[] scopes = new string[]
{
https://graph.microsoft.com/User.Read
};
var accessTokenRequest = app.AcquireTokenForClient(scopes);
var accessToken = accessTokenRequest.ExecuteAsync().Result.AccessToken;
Thx in advance!
List item
In a confidential client application, you usually have a cache per user. Therefore you will need to get the cache associated with the user and inform the application builder that you want to use it. In the same way, you might have a dynamically computed redirect URI.
could you please add below code ,
TokenCache userTokenCache = _tokenCacheProvider.SerializeCache(app.UserTokenCache,httpContext, claimsPrincipal);
please refer doc- Retrieve logged user info from microsoft graph in a framework .net environment .
if still it doesn't work, as you said it doesn't work , we would like to know what error you got?

How can I create an ASP.NET Identity user that can sign in?

I have an ASP.NET web application that has internal individual user accounts. I want to create those user accounts from an external program. So I have a program that references Microsoft.AspNet.Identity. In it I create users:
var userStore = new UserStore<IdentityUser>();
var um = new UserManager<IdentityUser>(userStore);
//...
var newUser = new IdentityUser(userName);
newUser.Email = userName;
var result = um.Create(newUser, "P#ssword1");
However, when I run the first application and try to sign in, SignInManager.PasswordSignInAsync always returns SignInStatus.Failure. (I'm quite sure the username and password are correct; I'm copying the username from the database and copying the password from the code.) Shouldn't it work? Am I missing something?
It turns out the culprit was IdentityUser. I don't know why (I'm guessing securitystamp has something to do with it), but you need to make ApplicationUsers. So I included a reference to the web application so I could make an ApplicationUser instead of an IdentityUser:
var userStore = new UserStore<ApplicationUser>(new ApplicationDbContext());
var um = new UserManager<ApplicationUser>(userStore);
//...
var newUser = new ApplicationUser();
newUser.Email = user.UserName;
newUser.UserName = user.UserName;
var result = um.Create(newUser, "P#ssword1");

Check if a password is valid using ASP.NET Identity 2

On my website, I give the administrators the possibility to change someone's password without entering the old one. I do the following:
userManager.RemovePassword(oldUser.Id);
userManager.AddPassword(oldUser.Id, newPassword);
However, this changes the password only if the newPassword string complies with the password policy set in the configuration files. AddPassword seems to fail silently when the new password does not fulfil the requirements.
Is there some simple way to check if a password is valid according to the current policy, apart from the obvious "manual procedure" (check how many upper/lowercase chars there are, how many digits, etc.). I'm looking for something like
bool valid = IsPasswordValid("pass");
You may be able to use the PasswordValidator.ValidateAsync() method to determine if a password meets the criteria defined in your UserManager :
var valid = (await UserManager.PasswordValidator.ValidateAsync("pass")).Succeeded;
You can simply use PasswordValidator to check for password validity and errors as shown below:
var passwordValidator = new PasswordValidator<IdentityUser>();
var result = await passwordValidator.ValidateAsync(_userManager, null, "your password here");
if (result.Succeeded)
{
// Valid Password
}
else
{
// Check the error messages in result.Errors
}
Above solution works for Asp.Net Core 2.2
In Net.Core 2.2, I did this. I collect the errors into a string list as I send them back via JSON using a mechanism that standard throughout my application. Thanks to cularbytes
List<string> passwordErrors = new List<string>();
var validators = _userManager.PasswordValidators;
foreach(var validator in validators)
{
var result = await validator.ValidateAsync(_userManager, null, newPassword);
if (!result.Succeeded)
{
foreach (var error in result.Errors)
{
passwordErrors.Add(error.Description);
}
}
}

how to skip facebook app permissions dialog

Here, I am trying to authenticate user via login and after that I want to skip permissions dialog. But I am unable to achieve this, as it always asking for permissions for app to the user. My intention is if user is not logged into the facebook he/she should be prompted for facebook login and then I will fetch public information by using method Get("/me"). Let me know what I am doing wrong here.
public string GetFBAccessToken(string strAppID, string strAppSecret, string strUrl)
{
// Declaring facebook client type
var vFB = new FacebookClient();
string strAccessTok = string.Empty;
try
{
if (!string.IsNullOrEmpty(strAppID) && !string.IsNullOrEmpty(strAppSecret) && !string.IsNullOrEmpty(strUrl))
{
// Getting login url for facebook
var loginUrl = vFB.GetLoginUrl(new
{
client_id = strAppID,
client_secret = strAppSecret,
redirect_uri = strUrl,
response_type = "code",
state = "returnUrl",
//scope = "",
display = "popup"
});
// Redirecting the page to login url
if (HttpContext.Current.Request.QueryString["code"] == null)
{
HttpContext.Current.Response.Redirect(loginUrl.AbsoluteUri);
}
// Fetching the access token from query string
if (HttpContext.Current.Request.QueryString["code"] != null)
{
dynamic result = vFB.Post("oauth/access_token", new
{
client_id = strAppID,
client_secret = strAppSecret,
redirect_uri = strUrl,
code = HttpContext.Current.Request.QueryString["code"]
});
// Getting access token and storing in a variable
strAccessTok = result.access_token;
}
}
return strAccessTok;
}
catch (Exception ex)
{
//if (HttpContext.Current.Request.QueryString["response_type"] == "code")
//{
// var fb = new FacebookClient();
// var details = fb.Get("/me");
//}
return strAccessTok;
}
}
Regardless to the platform/ language you are using; solution can be as follows.
check use's logged in status. https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus/
based on Response status, forcefully call your action (i.e. Log in, Get Permission or any additional action if user is already connected). For Log in check this reference document from FB. https://developers.facebook.com/docs/facebook-login/login-flow-for-web/
No. You cannot skip the Login Dialog.
In fact, it is really important for an APP owner to build a trust relationship with your users. I would recommend you to follow the Login Best Practices while authenticating the users using your APP.

Get Current User ASP.NET Visual Studio 2013 Preview ClaimsPrinciple

I'm trying to get the current user in a web forms project using the new Visual Studio 2013 Preview for Web. I'm able to get the username using Page.User, but trying to get the user id is where I'm stuck. It's using this new Identity Model thing they've come out with.
This is what I've got:
//Gets the correct username
string uname = User.Identity.Name;
//Returns a null object
Microsoft.AspNet.Identity.IUser user = IdentityConfig.Users.Find(uname);
//What I hope to call to add a user to a role
IdentityConfig.Roles.AddUserToRole("NPO", user.Id);
If you are using the Default Membership that come's with the ASP.NET WebForms Template you should do something like this to retrieve the user:
if (this.User != null && this.User.Identity.IsAuthenticated)
{
var userName = HttpContext.Current.User.Identity.Name;
}
The new model you are talking about is ClaimsPrincipal. The unique difference is this Claims Based Secury, that is completly compatible with the older versions but more powerfull.
EDIT:
To add an user to some Role programaticaly you should do this, passing the user name and the role name:
if (this.User != null && this.User.Identity.IsAuthenticated)
{
var userName = HttpContext.Current.User.Identity.Name;
System.Web.Security.Roles.AddUserToRole(userName, "Role Name");
}
Using the new Claim Based Security
if (this.User != null && this.User.Identity.IsAuthenticated)
{
var userName = HttpContext.Current.User.Identity.Name;
ClaimsPrincipal cp = (ClaimsPrincipal)HttpContext.Current.User;
GenericIdentity genericIdentity;
ClaimsIdentity claimsIdentity;
Claim claim;
genericIdentity = new GenericIdentity(userName, "Custom Claims Principal");
claimsIdentity = new ClaimsIdentity(genericIdentity);
claim = new Claim(ClaimTypes.Role, "Role Name");
claimsIdentity.AddClaim(claim);
cp.AddIdentity(claimsIdentity);
}
The user id is stored in the ClaimTypes.NameIdentifier claim by default. We provided an extension method as well that lives in Microsoft.AspNet.Identity so you can simply call Page.User.Identity.GetUserId(), instead of fetching the user just to get out the id.
Just a post for people who find this today this is now very easy to accomplish
ApplicationUserManager manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
ApplicationSignInManager signinManager = Context.GetOwinContext().GetUserManager<ApplicationSignInManager>();
ApplicationUser user = signinManager.UserManager.FindByNameAsync("username").Result;
At this point you have access to everything Id, Email, Phone number, Even the Hashed version of the user password.

Resources