Server-side Blazor page post to Razor page http error 400 - razor-pages

I am trying to post my username and password from a Blazor page (.razor) to a Razor Page(.cshtml) but I get http error 400 all the time.
LoginControl.razor
<form method="post" action="login">
<input type="text"
name="username"
#bind="#Username"
placeholder="User Name" />
<input type="password"
name="password"
placeholder="Password"
#bind="#Password" />
<button class="ml-md-auto btn btn-primary">Loggin</button>
</form>
Login.cshtml.cs
public async Task<IActionResult> OnPostAsync([FromServices] IUserProvider provider, string username, string password)
{
Login stuff
}

Bad request (400) means that the server cannot understand you
The method="post" is not applicable in Blazor or any other SPA frameworks. In Blazor there is special code that prevent a post back. Of course you can force a postback, which means that your Blazor page expires, and if you try to return to it, it is rerendered, and all your previous state is lost.
What you're trying to do here is to get the user's credentials in a Blazor component, and then try to post the data to a Razor Page Model for validation. You can't do that, and you should not do that. You should redirect your user to a login page in which he enters his credentials and those credentials should be validated against some sort of store, say SqlServer database, and then returns to the Blazor app. Remember, the redirection to a Razor Page means that your Blazor app has expired. Once again you do not post the user's credentials to the Login Razor Page. The user should enter his his credentials on Login.cshtml
I'd suggest you to use the Blazor built-in system to enable authentication and authorization. This system uses the Identity Ui (Razor Pages) to authenticate the user. It does exactly what you're trying to do. See here.... Also, use the Forms Components provided by Blazor, such as EditForm, InutText, etc.

Related

node.js backend, sveltekit frontend -> LDAP authentication / Active Directory group

I have built an app with a node.js backend and a sveltekit frontend.
It is actually finished apart of authentication, so that I can hide/disable some menuitems/routes.
The app is running in an Active Directory managed company network.
My current idea how to implement the authentication would be:
get the current logged in user name
check if the user is provisioned in a specific AD-group (which I use for my app, like groupname MY_APP_ADMIN, MY_APP_USER)
hide/disable the menuitem in the frontend (with some kind of global variable/store, like:
{#if adgroup === 'MY_APP_ADMIN'}
<form action="/adminarea" method="POST">
<button class="btn btn-primary">Adminarea</button>
</form>
{/if}
I would like to know if my approach is correct or if this is totally wrong...
Also it would be appreciated, if somebody has some code examples/implementations...
thx!
I have already tried out https://github.com/shaozi/ldap-authentication to connect to our LDAP:
let authenticated = await authenticate({
ldapOpts: { url: 'ldaps://companyLDAPTest:636' },
userDn:
'CN=MY TEST ADMIN USER,OU=xxx,OU=xxx,OU=xxx,DC=xxx,DC=xxx',
userPassword: 'MYPASSWORD',
})
console.log(authenticated)
-> Output: true
I have not been able yet to query the AD group membership :-/
I was now able to get the groups for a specific user and learned that I will have to have a login screen for the user and create an own session (token).

Send login_hint parameter from Shibboleth (Service provider) to Azure AD (Identity Provider)

We installed Shibboleth SP3 on our IIS instance, it works pretty well to have a SSO authentication.
However, we want to pass a « login_hint » parameter to Azure (our IdP) to ease people with multiple accounts. This way, the login is already set if they are not connected yet and they just have to fill the form with their password.
Is there a way to pass a query string parameter from the initial http request to the Idp ?
For example, a user go to https://sp.server.com/index.html?login_hint=me#mail.com, then he is redirected to https://login.microsoft.com/... Where we want to add this parameter.
Best regards,
Pierre Soundirarassou
To send login_hint parameter from Service provider to Azure AD, try making use of SAML.
Security Assertion Markup Language (SAML ) is standard for exchanging authentication and authorization identities between security domains. It uses security tokens containing assertions to pass information between Identity Provider and Service Provider.
To redirect the user to a specific page after SSO try making use of RelayState or Goto parameter.
If you use RelayState parameter, you need to encode this value in URL like below:
RelayState=https%3A%2F%2Fhost1.example.com
If you using goto parameter, then make sure the resource of the URL stated in the goto parameter should exist in the resource list to redirect the user. If you do not include URL resource list, all resources included in URLs specified in the goto parameter are considered valid.
Please refer the sample snippet below if it is helpful:
<form method="post" action="https://sp.example.com/SAML2/SSO/POST" ...>
<input type="hidden" name="SAMLResponse" value="<response>" />
<input type="hidden" name="RelayState" value="<url>" />
...
<input type="submit" value="Submit" />
</form>
For more in detail, please refer the below links if helpful:
single sign on - SSO - SAML, Redirect a user to a specified landing page after successful log in - Stack Overflow.
How do I redirect to a specific page after a successful IdP or SP initiated login in AM (All versions)? - Knowledge - BackStage (forgerock.com).
https://www.componentspace.com/Forums/1579/How-to-pass-parameter-with-SP-initiated-sso-request

SharePoint custom page post form with windows authentication

I am new to SharePoint and want to understand how to get the logged in (windows authentication) user details when I submit a custom form to a co-hosted WCF endpoint?
**HTML**
<form action="/TestWCF/Submit" method="post">
First name: <input type="text" name="fname"><br>
Last name: <input type="text" name="lname"><br>
<input type="submit" value="Submit">
</form>
**WCF**
public void Submit(User user)
{
}
Does the rendered SharePoint page stores a cookie which I should pass along with my custom post method? because if its a asp.net web app I can get a token stored in client and send to server and validate it. but SharePoint I don't have much control.
The username is custom validated. This is done by the FarmService.Authentication.DistributorValidator class in the FarmService assembly. This class inherits from WCF class UserNamePasswordValidator and overrides the Validate method.
public class DistributorValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
throw new SecurityTokenException("Username and password required");
var repository = new DistributorRepository();
if (! repository.IsKnownDistributor(userName, password))
throw new FaultException(string.Format("Wrong username ({0}) or password ", userName));
}
}
Except for one detail which is absolutely essential. For username password authentication to work your server hosting the service needs an X509 certificate. Else all service invocations will fail. This certificate is specified in the service behavior.
<serviceCertificate findValue="Farm" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
First you need a certificate. Instead of buying one (which is bound to a specific server address and thereby as good as useless for testing purposes) you can create your own. The .net framework comes with tools to generate these and there are several tutorials how to use these tools. Far more easier is selfcert a pluralsight tool which takes care of the whole process in a couple of clicks.
What they don’t tell you here is that you have to run the tool as administrator, else it will crash most ungracefully. What the tool is also unclear about is where to store the generated certificate. By default it is stored in MyStore. When validating the certificate it’s trustworthiness depends on the location it is stored. When the store is not trusted a chain of validation is started. Instead of setting up a chain of certificates you can also directly store your certificate in a trusted store.
To consume this service add a service reference in the client. The mexHttpBinding in the service configuration enables to read all metadata form the service without any credentials.
Setting up a connection to the client requires some fiddling. Again not all of these settings are clear by default.
var endPoint = new EndpointAddress(new Uri(Farm.FarmUrl), EndpointIdentity.CreateDnsIdentity("Farm"));
var binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
var result = new CustomerDeskOperationsClient(binding, endPoint);
result.ClientCredentials.UserName.UserName = Farm.FarmUserName;
result.ClientCredentials.UserName.Password = Farm.FarmPassword;
Details can refer to A simple WCF service with username password authentication
Hope that helps!

Can we directly provide a policy name for Forgot your password link on Azure AD B2C SignIn Policy

I am using custom SignUp/SignIn policies and custom UI.
I have been through the posts on stackoverflow for "Forgot Your Password" functionality, which says the calling application need to read the error code and redirect to PasswordReset Policy.
When I Inspected the html, I found a href for forgotpassword link which is pointing to my signUpSignIn Policy.
<div class="password-label">
<label for="password">Password</label>
<a id="forgotPassword" tabindex="2" href="/domain.onmicrosoft.com/B2C_1A_signup_signin/api/CombinedSigninAndSignup/forgotPassword?csrf_token=xxxxxx&StateProperties=xxx & p=B2C_1A_signup_signin">Forgot your password?</a>
</div>
Is there any way that I can call the PasswordReset policy from the href directly, instead of catching the error code, as I am using custom policies.
Thanks,
You can send the user directly to the password reset policy from your application.
You can't send the user directly from a Sign-In/Sing-Up policy to the Password Reset Policy as described here.
UserVoice: Go Direct to Password Reset from Sign-In/Sign-Up

Unable to use bearer token to access AAD-secure Web API

I have an API app secured with Azure AD (AAD). I also have an AAD application for a consuming application, and in the consuming application I have set up permissions to access the API app.
I am able to get a token, but when I go to use the token, the API app doesn't seem to look at the Authorization header. It tries to log me in via web browser.
My request looks like this:
GET /api/ticketing/issueTopics HTTP/1.1
Host: <removed>
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc<rest is removed>
Cache-Control: no-cache
This is what my Fiddler looks like.
The result I get in Postman is some MS redirect page:
<html>
<head>
<title>Working...</title>
</head>
<body>
<form method="POST" name="hiddenform" action="<removed>/.auth/login/aad/callback">
<input type="hidden" name="id_token" value="<bearer token removed>" />
<input type="hidden" name="state" value="/api/ticketing/issueTopics" />
<input type="hidden" name="session_state" value="<removed>" />
<noscript>
<p>Script is disabled. Click Submit to continue.</p>
<input type="submit" value="Submit" />
</noscript>
</form>
<script language="javascript">document.forms[0].submit();</script>
</body>
The bearer token I removed, when deserialized, has my information in it, not my consuming application. So, it's trying to authenticate me, rather than using the bearer token to authenticate.
Any ideas how to fix this?
Update 1
By means of update, I pulled down the servicePrincipal data related to my consuming application, and it clearly says the consuming app should be able to talk to the API app.
"oauth2Permissions": [{
"adminConsentDescription": "Allow the application to access Ticketing API on behalf of the signed-in user.",
"adminConsentDisplayName": "Access Ticketing API",
"id": "<removed>",
"isEnabled": true,
"type": "User",
"userConsentDescription": "Allow the application to access Ticketing API on your behalf.",
"userConsentDisplayName": "Access Ticketing API",
"value": "user_impersonation"
}]
Update 2
I made a console app to try it that way. I got a 401 (Unauthorized).
An interesting observation is that if I go to jwt.io and paste my token in, it is able to deserialize it, but it also says the token is invalid (Invalid Signature). Not sure what that implies.
I figured out the issue after figuring out how to turn on detailed logging and pouring through them.
Documentation on MSDN says to pass "resource" as the App ID Uri. But you actually need to pass the Client ID as the value for "resource." Once I changed that, everything worked perfectly.
I found this in a txt file in LogFiles\Application.
2016-07-12T15:48:39 PID[8584] Warning JWT validation failed: IDX10214: Audience validation failed. Audiences: 'https://<removed>.azurewebsites.net'. Did not match: validationParameters.ValidAudience: '0b61abb8-59...7-6046c22f9c92' or validationParameters.ValidAudiences: 'null'.
Incorrect documentation I was looking at:
https://msdn.microsoft.com/en-us/library/partnercenter/dn974935.aspx
https://msdn.microsoft.com/en-us/library/azure/dn645543.aspx (this was the biggest offender as it does exactly what I want to do with incorrect information)
Are you using "UseWindowsAzureActiveDirectoryBearerAuthentication"?
In the Web API you should use it, add it in the Startup Config. As following:
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = ConfigurationManager.AppSettings["ida:Audience"],
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
});
Hope this works for you,
Regards!

Resources