ADAL Authentication Error Multi-Tenant - c#

I taken the sample code from the GIT for multi-tenant.
https://github.com/OfficeDev/O365-WebApp-MultiTenant
In https://manage.windowsazure.com/ i enabled MULTI-TENANT to YES. But when ever i tried to login with different organization i am getting error as follows.
User account 'vtest#someconsuting.onmicrosoft.com' from identity provider 'https://sts.windows.net/xxxxxxxxxxxxxxxxxxxxxxxxxxx/' does not exist in tenant 'My Test App ' and cannot access the application 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' in that tenant. The account needs to be added as an external user in the tenant first. Sign out and sign in again with a different Azure Active Directory user account.
How can i resolve this??

Finally i found the solution to my problem. From this URL https://github.com/dream-365/OfficeDev-Samples/blob/master/samples/Office365DevQuickStart/AspNetMvc-MultiTenant/
I copied the following files to my project
TokenCacheDBContext.cs
SqlDBTokenCache.cs
ServiceConstants.cs
App_Start/Startup.auth.cs
I ran the project and got one error for Office365AssertedFailedException. For that i created one more class file like
Office365AssertedFailedException.cs
I rebuild the code again and got success. Now i am able to login with multi-tenants.

Please ensure your authority url is "https://login.windows.net/common".
If your authority url is "https://login.windows.net/{tenant_id}", you will get the error as following:
To fix this issue, in the Startup.Auth.cs, config the authority url as "https://login.windows.net/common".
var authority = string.Format("{0}/{1}", ServiceConstants.AzureADEndPoint, "common");
var options = new OpenIdConnectAuthenticationOptions {
ClientId = OAuthSettings.ClientId,
Authority = authority,
TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters {
ValidateIssuer = false
}
};
sample Startup.Auth.cs

I had the same issue. Just replaced
string authorityUri = "https://login.microsoftonline.net/common/";
with
string authorityUri = "https://login.windows.net/common";

Related

Website Azure connection on mulitple subdomains

We are hosting a website on our webserver. That website needs to connect to Azure/Adfs. Users need to login through Azure/Adfs to access some parts of the site.
But it only works half. I can connect on "customer.nl", but on "subdomain.customer.nl" I get a "NONCE error".
There is a "Startup" class, which inherits from "UmbracoDefaultOwinStartup" (an Umbraco override for the regular OwinStartup). The class has a "ConfigureAuth" method, which sets the configurationparameters. One of them is the RedirectUri, and it's set (via web.config) to "customer.nl".
The "startup" code:
[assembly: OwinStartup(typeof(Ip.Startup))]
namespace Customername {
public class Startup : UmbracoDefaultOwinStartup {
string redirectUri = System.Configuration.ConfigurationManager.AppSettings["RedirectUri"];
public new void Configuration(IAppBuilder app) {
ConfigureAuth(app);
app.MapSignalR();
base.Configuration(app);
}
public void ConfigureAuth(IAppBuilder app) {
app.SetDefaultSignInAsAuthenticationType(
CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions(){
CookieManager = new SystemWebCookieManager()
});
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions {
ClientId = clientId,
Authority = authority,
RedirectUri = redirectUri,
PostLogoutRedirectUri = redirectUri,
Scope = OpenIdConnectScope.OpenIdProfile,
ResponseType = OpenIdConnectResponseType.IdToken,
TokenValidationParameters = new TokenValidationParameters() {
ValidateIssuer = false
},
Notifications = new OpenIdConnectAuthenticationNotifications {
AuthenticationFailed = OnAuthenticationFailed
}
});
}
}
}
If I try to login on "subdomain.customer.nl", I redirected to login.microsoftonline.com but I see a "redirect_url=customer.nl" in the URL.
The function to redirect a unauthenticated user is:
public void SignIn(string ReturnUrl = "/") {
if (!Request.IsAuthenticated) {
HttpContext.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties { RedirectUri = ReturnUrl },
OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
}
}
But changing the RedirectUri in this function doesn't change the 'Redirect_Uri' in the login.microsoftonline.com url.
If I login on subdomain.customer.nl, I get returned to customer.nl with the following querystring (I've decoded the URL):
https://www.customer.nl/?errormessage=IDX21323:
RequireNonce is '[PII is hidden]'.
OpenIdConnectProtocolValidationContext.Nonce was null,
OpenIdConnectProtocol.ValidatedIdToken.Payload.Nonce was not null.
The nonce cannot be validated.
If you don't need to check the nonce, set OpenIdConnectProtocolValidator.RequireNonce to 'false'. Note if a 'nonce' is found it will be evaluated.
My guess is that the NONCE error pops up when the redirect_uri doesn't match the origin-url (subdomain.customer.nl != customer.nl).
Is this correct? And if so, how can I change the Redirect_Uri to the subdomain a user is visiting? Setting it on startup isn't the way to go, it seems.
• Firstly, I would suggest you to please ensure that public DNS records exist for the subdomains that you want to connect to through the base domain URL, i.e., ‘customer.nl’. The public DNS records for the subdomains can be ‘A’ host records, ‘TXT’ records but need to be configured correctly within your public DNS server and pointing to a public IP address if independent web applications are hosted on them.
• Secondly, since you seem to use Azure AD authentication in your website for redirecting to the subdomain, I would suggest you configure the redirect URI for the concerned subdomains in the Azure AD registered application for the base domain such that after successful Azure AD authentication, the web application gets correctly redirected to subdomain page as desired.
For more information on the above, kindly refer to the documentation link below: -
https://learn.microsoft.com/en-us/azure/app-service/configure-authentication-provider-aad
But changing the RedirectUri in this function doesn't change the 'Redirect_Uri' in the login.microsoftonline.com url
You can do the above by delegating the required API permissions and scope to the Azure function application in your registered Azure AD application. Kindly refer to the documentation link below for your reference: -
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent
Also, the domains for the authentication request and the response need to be matched as it stores the ‘nonce’ and the ‘state’ for CSRF login attacks mitigation. Thus, I would like to suggest you consider the scenario below for different clients (as per your redirection mechanism) and take advantage of SSO: -
a) The user logs in into the first application (customer.nl). The callback URL belongs to this app.
b) After processing the callback (on the ‘parseHash’ callback function), redirect the user to the subdomain URL.
c) When the user lands on the subdomain URL app, the app will see that there’s no session for the user and ask Azure AD for authentication (either authorize () or checkSession()). If the user already has a session in Azure AD, there will be no prompt to the user and a new authentication response will be provided to the app.
If you are using universal login (as opposed to embedded login as above), when the user clicks on “Login” on the base domain URL (customer.nl) app, you send the user directly to the SPA, pointing to a login initiation endpoint (e.g.: - https://app.mydomain.com/login 1), and have the subdomain URL app start the actual login flow.
For more information regarding the above, I request you to please refer the below link: -
https://community.auth0.com/t/log-in-from-different-subdomain-produces-state-error/19116

Trying to login with Azure AFDS on multiple domains

I'm trying to connect to an Azure AD server with an Umbraco website.
To start off, I have no knowledge of Azure. There is a third party who administers the Azure part.
We use OWIN to connect to Azure via OpenID.
OnStartup:
public void ConfigureAuth(IAppBuilder app){
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions{
// Sets the ClientId, authority, RedirectUri as obtained from web.config
ClientId = clientId,
Authority = authority,
RedirectUri = redirectUri,
PostLogoutRedirectUri = redirectUri,
Scope = OpenIdConnectScope.OpenIdProfile,
ResponseType = OpenIdConnectResponseType.IdToken,
TokenValidationParameters = new TokenValidationParameters(){
ValidateIssuer = false
},
Notifications = new OpenIdConnectAuthenticationNotifications{
AuthenticationFailed = OnAuthenticationFailed
}
});
}
The SignIn function in the SurfaceController:
public void SignIn(string ReturnUrl = "/"){
if (!Request.IsAuthenticated) {
HttpContext.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties { RedirectUri = ReturnUrl },
OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
}
Here come the non-working part.
If I test this site at a local domain (only available from within our office), it works.
If I test this site on a publicly-available staging domain, it works.
If I test this site on a live domain, it works.
But as soon as I change a sub-domain, I get send to the working domain with a "RequireNonce" error.
So for example:
https://customer.localdomain.com -> login -> I return logged in at https://customer.localdomain.com.
https://test.localdomain.com -> login -> I return to https://customer.localdomain.com (notice the domain), with a "Nonce-error".
https://customer.stagingdomain.com -> login -> I return logged in at https://customer.stagingdomain.com.
https://test.stagingdomain.com -> login -> I return to https://customer.stagingdomain.com (notice the domain), with a "Nonce-error".
https://www.livedomain.com -> login -> I return logged in at https://www.livedomain.com.
https://test.livedomain.com -> login -> I return to https://www.livedomain.com (notice the domain), with a "Nonce-error".
The complete error is:
IDX21323:
RequireNonce is '[PII is hidden]'.
OpenIdConnectProtocolValidationContext.Nonce was null,
OpenIdConnectProtocol.ValidatedIdToken.Payload.Nonce was not null.
The nonce cannot be validated.
If you don't need to check the nonce, set OpenIdConnectProtocolValidator.
RequireNonce to 'false'. Note if a 'nonce' is found it will be evaluated.
What can we do to resolve this problem? Our customer has a couple of subdomains (seperate sites) that all need this login functionality.
We've tried adding subdomains to a reply-list in Azure (well, the third party added them for us), but that didn't solve the problem.
Is it possible to just turn RequireNonce off somewhere?
Thank you JamesHamil-MSFT Posting your suggestion as an answer to help other community members .
"The problem was that the time or automatic reference program service binding a custom domain name.
After the application network management is configured. The Host IP that modifies the custom domain name points to a public IP that is gateway."
Please try checking that your domain is configured correctly and points to the correct gateway."
Please refer the below links for further information:
. Configure App Service with Application Gateway using PowerShell | MS DOC .
. SO THREAD for similar issue.

OpenID connect ADFS 2019 - authority invalid

Following the documentation example on microsoft for the adfs setup.
ADFS microsoft setup
I have the following application .Net 4.6.
startup.cs
app.UseMyAppApiAuthentication(config);
in the class
//setup OpenIdConnect Authentication
var options = config.DependencyResolver.GetService<OpenIdConnectAuthenticationAndNotificationOptions>();
app.UseOpenIdConnectAuthentication(options);
In the options class i have
ClientId = configProvider.GetOpenIdConnectClientId();
Authority = configProvider.GetOpenIdConnectAuthority();
PostLogoutRedirectUri = configProvider.GetOpenIdConnectPostLogoutRedirectUri();
RedirectUri = configProvider.GetOpenIdConnectRedirectUri();
Notifications = new OpenIdConnectAuthenticationNotifications()
{
AuthorizationCodeReceived = authenticationNotificationProcessor.OnAuthorizationCodeReceived,
AuthenticationFailed = authenticationNotificationProcessor.OnAuthenticationFailed
};
where authority is
public string GetOpenIdConnectAuthority()
{
var instance = ConfigurationManager.AppSettings["moto:AADInstance"];
var tenant = ConfigurationManager.AppSettings["moto:Tenant"];
return String.Format(CultureInfo.InvariantCulture, instance, tenant);
}
In the webconfig, I have the clientid and client secret set, I have the AADinstance set and tenant is blank.
If I put in the ADFS URI. I get the following error:
Now if I edit the AADinstance and add /.well-known/Openid-configuration i get a different error...
I have also changed the config and removed authority and replace with "MetadataAddress" still no change.
What do I need todo to resolve this issue?
Note: if I change the redirect URI to something different when running the app, I manage to get to the adfs login screen with the error that there is a mismatch with the redirect.
I recommend you to open a support case since it needs deep troubleshooting in order to isolate the issue.

Application is not supported over the /common or /consumers endpoints. Please use the /organizations or tenant-specific endpoint

I know there are several other posts listed about this topic but I cannot seem to find any useful info in them to apply to my own application. I am building a .Net MVC Web App that uses the Microsoft Graph API. I followed another project (https://github.com/microsoftgraph/aspnet-snippets-sample) but when I launch the application, it redirects to https://login.microsoftonline.com where it attempts to log in using a Microsoft work account, and redirects back to the homepage. However, after entering Microsoft account credentials and before being redirected back, I am shown an error:
.
Below is a section from my Startup.Auth.cs that I believe is causing the problems. If anyone can see anything that seems off or has any insight on this topic, I would greatly appreciate it. I have been spinning my wheels just trying to sign-in to this application using Open Id Connect to be able to use the Microsoft Graph API. Thanks!
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions {
// The `Authority` represents the v2.0 endpoint - https://login.microsoftonline.com/common/v2.0
// The `Scope` describes the permissions that your app will need. See https://azure.microsoft.com/documentation/articles/active-directory-v2-scopes/
ClientId = appId,
* * Authority = String.Format(CultureInfo.InvariantCulture, aadInstance, "common", "/v2.0"), * *
RedirectUri = redirectUri,
Scope = scopes,
PostLogoutRedirectUri = redirectUri,
TokenValidationParameters = new TokenValidationParameters {
ValidateIssuer = false,
},
Notifications = new OpenIdConnectAuthenticationNotifications {
AuthorizationCodeReceived = async(context) => {
var code = context.Code;
string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
string graphScopes = nonAdminScopes;
string[] scopes = graphScopes.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
ConfidentialClientApplication cca = new ConfidentialClientApplication(appId, redirectUri,
new ClientCredential(appSecret),
new SessionTokenCache(signedInUserID, context.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase).GetMsalCacheInstance(), null);
AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(code, scopes);
// Check whether the login is from the MSA tenant.
// The sample uses this attribute to disable UI buttons for unsupported operations when the user is logged in with an MSA account.
var currentTenantId = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
if (currentTenantId == "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") {
HttpContext.Current.Session.Add("AccountType", "msa");
}
// Set IsAdmin session variable to false, since the user hasn't consented to admin scopes yet.
HttpContext.Current.Session.Add("IsAdmin", false);
},
AuthenticationFailed = (context) => {
context.HandleResponse();
context.Response.Redirect("/Error?message=" + context.Exception.Message);
return Task.FromResult(0);
}
}
});
This error is usually caused by an incompatibility between your app registration and the authentication library you are using.
The code in that sample is using the Microsoft Authentication Library (MSAL), which uses the Azure V2 OAuth endpoints, which supports converged auth (both Azure AD accounts and Microsoft accounts). In order for the v2 auth endpoints to work, your app registration MUST come from https://apps.dev.microsoft.com.
If you register your app on the Azure portal (https://portal.azure.com), you'll see this error. That's because the Azure portal registers the app using the Azure v1 OAuth schema.
There is also a case where the https://apps.dev.microsoft.com portal can create a v1 registration. If you login to that portal and you see more than one grouping of apps, with multiple "Add an app" buttons, you need to choose the "Add an app" button for Converged Apps.
If you are using microsoftgraph/msgraph-sdk-dotnet-auth for getting access token, then /common endpoint is valid.
If you are using AzureAD/microsoft-authentication-library-for-java for getting access token, then use /organizations endpoint instead of /common.
Unfortunatelly adding Converged Apps from https://apps.dev.microsoft.com/ is no longer supported by MS. They redirect to Azure portal from there.

azure data lake authorization

I am new to Azure Data Lake Analytics and am converting a C# batch job to use service to service authentication before submitting stored procedures to Azure Data Lake Analytics.
public void AuthenticateADLUser()
{
//Connect to ADL
// Service principal / appplication authentication with client secret / key
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
cTokenCreds = ApplicationTokenProvider.LoginSilentAsync(strDomain, strWebApp_clientId, strClientSecret).Result;
SetupClients(cTokenCreds, strSubscriptionID);
}
public static void SetupClients(ServiceClientCredentials tokenCreds, string subscriptionId)
{
_adlaClient = new DataLakeAnalyticsAccountManagementClient(tokenCreds);
_adlaClient.SubscriptionId = subscriptionId;
_adlaJobClient = new DataLakeAnalyticsJobManagementClient(tokenCreds);
_adlsFileSystemClient = new DataLakeStoreFileSystemManagementClient(tokenCreds);
}
Even though I have given it the correct ClientId the error comes back with a different ClientID in the error when I execute the following code:
var jobInfo = _adlaJobClient.Job.Create(_adlsAccountName, jobId, parameters);.
The error message is:
The client 'e83bb777-f3af-4526-ae34-f5461a5fde1c' with object id 'e83bb777-f3af-4526-ae34-f5461a5fde1c' does not have authorization to perform action 'Microsoft.Authorization/permissions/read' over scope '/subscriptions/a0fb08ca-a074-489c-bed0-....
Why is the ClientID different than the one I used in the code?
Is this a code issue or a permissions issue? I assume that it is code since the ClientID is not an authorized one that I created.
note: The SubscriptionId is correct.
I assumed you created an Azure Active Directory App and are you the client and domain IDs of this app. If not, you'll need that... If you do have that, then can you check if the App has permissions over your Data Lake Store: https://learn.microsoft.com/en-us/azure/data-lake-store/data-lake-store-authenticate-using-active-directory
Had exactly same symptoms. WebApp was created in AAD in portal originally to access Azure Data Lake Store and same code-snippet worked perfectly. When I decided to re-use same WebApp (clientid/secret) it failed with same error, even though I have given reader/contributor roles on sub/RG/ADLA to the App.
I think the reason is that WebApp underneath has a "service principal" object (thus error msg shows different object id) and ADLA uses it for some reason. Mine didn't have credentials set - empty result:
Get-AzureRmADSpCredential -objectid <object_id_from_error_msg>
Added new password as described here
New-AzureRmADSpCredential -objectid <object_id_from_error_msg> -password $password
Used the pwd as secret in LoginSilentAsync, clientId was left as before - WebApp clientId (not the principal object id shown in the error)
I wasn't able to find this principal info in portal, only PS.

Categories

Resources