I need to enable user to reset the password on "Page resetting password" and sending via email the link to set up new password.
How do I generate URL for new password setting after generating 'reset token' ?
I cannot pass result of GeneratePasswordResetTokenAsync(user) directly to URL due to the security settings and I do not want to compromise security by setting this in web.config:
<system.webServer>
<security>
<requestFiltering allowDoubleEscaping="true" />
</security>
</system.webServer>
I generate the token usinng GeneratePasswordResetTokenAsync method:
string code = await _userManager.GeneratePasswordResetTokenAsync(user);
I have finally used this code fragment inspired by BlazorHero project:
string code = await _userManager.GeneratePasswordResetTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var route = "set-password";
var origin = "https://localhost:44375"; // FIXME
var endpointUri = new Uri(string.Concat($"{origin}/", route));
var passwordResetURL = QueryHelpers.AddQueryString(endpointUri.ToString(), "Token", code);
passwordResetURL is URL which can be sent via email and opened by the user.
Related
We have a validate jwt policy in APIM to validate jwt token. we are generating token from our function app using the azure.identity library. till now we were using system assigned identity for generating the token using the below method.
var tokenCredential = new DefaultAzureCredential();
var accessToken = await tokenCredential.GetTokenAsync(
new TokenRequestContext(scopes: new string[] { "https://management.azure.com" + "/.default" }) { });
token is generated successfully. and we are able to successfully validate the token in the policy. below is the APIM xml policy.
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Invalid or Expired token" require-expiration-time="true" require-signed-tokens="true">
<openid-config url="https://login.microsoftonline.com/tenantid/v2.0/.well-known/openid-configuration" />
<audiences>
<audience>https://management.azure.com</audience>
</audiences>
<issuers>
<issuer>https://sts.windows.net/tenantid/</issuer>
</issuers>
<required-claims>
<claim name="oid" match="any">
<value>objectid of the managed identity/system assigned</value>
</claim>
</required-claims>
</validate-jwt>
now we have assigned the user managed identity and assigned the identity to the function app with the below code I am able to generate the token but in APIM it was throwing weird error.
var azureServiceTokenProvider = new ManagedIdentityCredential(clientId: "client-id-of-managed-identity-id");
accessToken = await azureServiceTokenProvider.GetTokenAsync(new Azure.Core.TokenRequestContext(new[] { "https://management.azure.com" + "/.default" }));
APIM is telling
"JWT Validation Failed: IDX10501: Signature validation failed. Unable to match key: \nkid: ''.\nExceptions caught:\n ''.
any idea on how to overcome this ?
I have updated my code to use DefaultAzureCredential instead of ManagedIdentityCredential and it started working.
var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions
{ ManagedIdentityClientId = "managed_identity_clinet_id" });
AccessToken accessToken = await credential.GetTokenAsync(
new TokenRequestContext(scopes: new string[] { "https://management.azure.com" + "/.default" }) { });
I passed the client ID of the managed Identity and able to proceed with the generated token.
I have the following KeyCloak Client config, to use pkce authentication flow:
Realm: REALM
Client ID: pkce-client
Client Protocol: openid-connect
Access Type: public
Standard Flow Enabled: ON
Valid Redirect URIs: http://localhost:4200/
Advanced Settings:
Proof Key for Code Exchange Code Challenge Method: S256
I try to authenticate in a flutter App with iOS Simulator via openid_client
https://pub.dev/packages/openid_client like this
authenticate() async {
var uri = Uri.parse('http://$localhost:8180/auth/realms/REALM');
var clientId = 'pkce-client';
var scopes = List<String>.of(['profile', 'openid']);
var port = 4200;
var redirectUri = Uri.parse(http://localhost:4200/);
var issuer = await Issuer.discover(uri);
var client = new Client(issuer, clientId);
urlLauncher(String url) async {
if (await canLaunch(url)) {
await launch(url, forceWebView: true);
} else {
throw 'Could not launch $url';
}
}
var authenticator = new Authenticator(
client,
scopes: scopes,
port: port,
urlLancher: urlLauncher,
redirectUri: redirectUri,
);
var auth = await authenticator.authorize();
var token= await auth.getTokenResponse();
return token;
}
But it only gives me this web view:
The Terminal where KeyCloak is running gives me the following lines:
INFO [org.keycloak.protocol.oidc.endpoints.AuthorizationEndpointChecker] (default task-34) PKCE enforced Client without code challenge method.
WARN [org.keycloak.events] (default task-34) type=LOGIN_ERROR, realmId=REALM, clientId=pkce-client, userId=null, ipAddress=127.0.0.1, error=invalid_request, response_type=code, redirect_uri=http://localhost:4200/, response_mode=query
When using Postman it worked and it provided me the Login page:
But I have additional parameters there, which I do not know where to add them in Authenticator(..) when using openid_client, state is automatically added.
state: <state>
code_challenge: <code-challenge>
code_challenge_method: S256
Do I need to add these code_challenge parameters somewhere in the openid_client method?
Or do I need to change the redirect URL when using an App? I tried with the package_name like proposed here (https://githubmemory.com/repo/appsup-dart/openid_client/issues/32), but it did not work either.
See the source code:
: flow = redirectUri == null
? Flow.authorizationCodeWithPKCE(client)
: Flow.authorizationCode(client)
You have specified redirectUri, so authorizationCode flow was used. But you want authorizationCodeWithPKCE flow in this case. So just make sure redirectUri is null and correct PKCE flow (with correct url parameters, e.g. code_challenge) will be used.
You need to send the redirectUri:null and set the port to 3000 ( you can use your port ).
after that you need to add the redirect uri in keycloak like this http://localhost:3000/ .it will do the trick
(what happening is when you send the redirect uri as null value, open_id client use the pkce flow and use the default url)
It's been three days that I have been trying to find a solution for the exception that I am getting for the following code to validate a Graph API token:
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(
$"{_authenticationSettings.Authority}/.well-known/openid-configuration",
new OpenIdConnectConfigurationRetriever());
var config = await configManager.GetConfigurationAsync();
_validationParameters = new TokenValidationParameters
{
IssuerSigningKeys = config.SigningKeys,
ValidateAudience = true,
// Audience MUST be the app ID aka clientId
ValidAudience = _authenticationSettings.ClientId,
ValidateIssuer = true,
ValidIssuer = config.Issuer,
ValidateLifetime = true
};
var tokenHandler = new JwtSecurityTokenHandler();
var result = tokenHandler.ValidateToken(authHeader.Parameter, _validationParameters, out var jwtToken);
The exception happens when calling ValidateToken and reads as below:
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException:
'IDX10511: Signature validation failed. Keys tried:
'System.Text.StringBuilder'. kid: 'System.String'. Exceptions
caught: 'System.Text.StringBuilder'. token:
'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'.'
I am really running out of reasons why this should happen. Any ideas or suggestions to fix this problem?
The packages are:
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.8.0" />
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="6.8.0" />
Even this solution was not conclusive too.
Validating a Token from the Graph API is a bit different than a standard OIDC Token.
See the following for more information:
https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609
Graph API tokens cannot and should not be validated and hence the signature validation fails. Please see this answer on GitHub.
I have sample WebForms application with Owin. Tried to do SAML2 authentication with Azure AD IdP. It works fine, user is registered in application and authenticated.
Now I need to use other IdP. So I changed my application and nothing.
Saml response contains success, so IdP authenticated me. But calling Context.GetOwinContext().Authentication.GetExternalLoginInfo() returns null.
I found some posts about "external cookie", but I don't think this is my problem, because Azure sample works fine. Switching to other IdP failed.
Only difference seems to be in SAML Xml format.
Azure returns as
<samlp:Response Destination="https://localhost:44390/Saml2/Acs"
ID="_5eaccd77-fa78-4f59-86d9-67049ef074ce" InResponseTo="id73419322f1cc440184f456548cee7d09"
IssueInstant="2018-12-21T15:00:58.248Z" Version="2.0"
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
</samlp:Response>
but other IdP returns as
<saml2p:Response Destination="https://localhost:44390/Saml2/Acs"
ID="_9547020d571863ef02c1f6d3dc8d94d7" InResponseTo="id46574a117a254f06a272ec02769b1a3c"
IssueInstant="2018-12-21T14:31:54.505Z" Version="2.0"
xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
</saml2p:Response>
But namespaces should be ok.
So it must be something in SAML response? How can I find problem?
private static Saml2AuthenticationOptions CreateSaml2Options()
{
var spOptions = CreateSpOptions();
var saml2Options = new Saml2AuthenticationOptions(false)
{
SPOptions = spOptions
};
var idp = new IdentityProvider(new EntityId("XXX"), spOptions)
{
AllowUnsolicitedAuthnResponse = true,
Binding = Saml2BindingType.HttpPost,
SingleSignOnServiceUrl = new Uri("XXX")
};
saml2Options.IdentityProviders.Add(idp);
return saml2Options;
}
private static SPOptions CreateSpOptions()
{
const string language = "cs-cz";
var spOptions = new SPOptions
{
EntityId = new EntityId("app:vwg.skoda.nia"),
AuthenticateRequestSigningBehavior = SigningBehavior.Always,
ReturnUrl = new Uri("https://localhost:44390/Saml2/Acs")
};
var attributeConsumingService = new AttributeConsumingService
{
IsDefault = true,
ServiceNames = { new LocalizedName("Saml 2 Authentication", "en") }
};
attributeConsumingService.RequestedAttributes.Add(new RequestedAttribute("Minimal"));
spOptions.AttributeConsumingServices.Add(attributeConsumingService);
var certPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "/App_Data/XXX.pfx";
var cert = new X509Certificate2(certPath, "XXX");
spOptions.ServiceCertificates.Add(cert);
return spOptions;
}
Sustainsys.Saml2.Exceptions.InvalidSignatureException: The signature verified correctly with the key contained in the signature, but that key is not trusted.
This means that the signature is correct, but that you have not configured the signing key as trusted.
You need to add a certificate with the idp's public key to the IdentityProvider.SigningKeys collection.
So I've set up everything to invite users to the registration page on my site and track their invitation code, but now whenever a user accepts the invitation they end up getting the following error:
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
And here's the URL:
http://www.facebook.com/dialog/oauth/?state=eyJyIjoiaHR0cDovL2FwcHMuZmFjZWJvb2suY29tL2Zpc2hhcndlLz9yZXF1ZXN0X2lkcz0xMDE1MDYzNzQzNDI4NTQ4NCwxMDE1MDYzNzU3NjA0MDQ4NCwxMDE1MDYzNzU4MDQ1NTQ4NCwxMDE1MDYzNzU5NzQ2MDQ4NCwxMDE1MDYzNzYxNDUyMDQ4NCwxMDE1MDYzNzYzMDg0NTQ4NCZyZWY9bm90aWYmbm90aWZfdD1hcHBfcmVxdWVzdCJ9&client_id=217174461634478&redirect_uri=http://www.fisharwe.com/facebookredirect.axd
Why is the redirect_uri http://www.fisharwe.com/facebookredirect.axd and not what I've set in my code using top.location.href="whatever.com"?
UPDATE:
Seems like that problem has been resolved somehow. But it still does not redirect to the registration page of my site! Here's the source code of the landing page:
<html><head><script type="text/javascript">
top.location = "http://www.facebook.com/dialog/oauth/?state=eyJyIjoiaHR0cDovL2FwcHMuZmFjZWJvb2suY29tL2Zpc2hhcndlLz90eXBlPWRpc2NvdmVyeSJ9&client_id=217174461634478&redirect_uri=http://www.fisharwe.com/facebookredirect.axd";
</script></head><body></body></html>
UPDATE2:
This is my C# code:
[CanvasAuthorize]
public ActionResult Index()
{
var fb = new FacebookWebClient(FacebookWebContext.Current);
dynamic requestInfo = fb.Get("/me/apprequests/");
var b = requestInfo.Count;
if (requestInfo.data.Count > 0)
{
var a = requestInfo["data"][0]["data"];
//ViewData.Add("TrackingData", a);
return Redirect(redirectUrl + "?code=" + a);
}
return RedirectToAction("Index", "Home");
}
have you setup the http handler in web.config?
<httpHandlers>
<add verb="*" path="facebookredirect.axd" type="Facebook.Web.FacebookAppRedirectHttpHandler, Facebook.Web" />
</httpHandlers>