azure-samples / active-directory-dotnet-webapp-openidconnect-aspnetcore Goto Github PK
View Code? Open in Web Editor NEWAn ASP.NET Core web application that signs-in Azure AD users from a single Azure AD tenant.
An ASP.NET Core web application that signs-in Azure AD users from a single Azure AD tenant.
I am trying to integrate Identityserver 4 with a Azure Active directory, but receive following error:
Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: IDX10501: Signature validation failed. Unable to match 'kid': 'RrQqu9rydBVRWmcocuXUb20HGRM', token: '{"alg":"RS256","typ":"JWT","x5t":"RrQqu9rydBVRWmcocuXUb20HGRM","kid":"RrQqu9rydBVRWmcocuXUb20HGRM"}.{"aud":"###########,"iss":"###########","iat":1479457186,"nbf":1479457186,"exp":1479461 086,"amr":["pwd"],"c_hash":"ZpWv18fS5_fPTxZgHITCrw","family_name":"Smith","given_name":"Bob","ipaddr":"127.0.0.1","name":"Bob Smith","nonce":"6361505428d5473221d.WYzMzZiMTUtZmNkMS00NjcwLTljMDktZDRlZTk2ZDk1ZjJlYzU0NTBkOTgtYTAzqkifdzQyLW88Dktw0YzAzNmE0M TRj","oid":"###########,"onprem_sid":"###########","platf":"3","sub":"###########","tid":"88cb0952-ee76-4b6e-a6c4-f7da82b4c15a","unique_name":"[email protected]","upn":"[email protected]","ver":"1.0"}'. at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters) at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken) at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.ValidateToken(String idToken, AuthenticationProperties properties, TokenValidationParameters validationParameters, JwtSecurityToken& jwt) at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.<HandleRemoteAuthenticateAsync>d__19.MoveNext()
I've tried most suggestions which were on the internet but I am getting desperate on solutions. Here is my configuration of the OIDC middleware so far:
`
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme, //same as "external"
SignOutScheme = IdentityServerConstants.SignoutScheme, //same as "idsrv"
DisplayName = "Azure AD",
ClientId = Configuration["Authentication:AzureAd:ClientId"],
Authority = Configuration["Authentication:AzureAd:AADInstance"] + Configuration["Authentication:AzureAd:TenantId"],
CallbackPath = "/signin-oidc",
ResponseType = "id_token",
TokenValidationParameters = new TokenValidationParameters {
NameClaimType = "name",
RoleClaimType = "role",
}
});
`
Any clue how to resolve this?
@dstrockis Happy T-Bird Day! 🐔 🍗
Something has changed in setting up notifications with OpenIdConnect middleware with .NET 5. This used to work ...
app.UseOpenIdConnectAuthentication(options => {
options.ClientId = ClientId;
options.Authority = $"https://login.microsoftonline.com/{Tenant}";
options.PostLogoutRedirectUri = PostLogoutRedirectUri;
options.AutomaticAuthenticate = true;
options.Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = (context) => {
return Task.FromResult(0);
},
...
}
});
... that's broken now ...
I can't find the extension method for Notifications
, and I lost OpenIdConnectAuthenticationNotifications
and can't find what package it was moved to or if it was removed and totally replaced with some other scheme.
Side Note: I wish they had an Announcements repo the way that the .NET 5 teams use that we could subscribe for automatic notifications of breaking changes. I'm cool with the fact of breaking changes ... I'm not having fun with breaking changes and there's no way to find out about them until your code blows up. I'm sure you appreciate my frustration.
Anyway ... do you know what's up with this? I see your samples don't show the changes yet, but I couldn't find a resource online explaining what they changed.
In the demo, the TenantId, and ClientId were automatically placed in the appsettings.json. My question is; do these two pieces of information need to be protected? Is it ok for them to be in the appsettings.json, and then in source control?
Or should these value be saved in the Secrets Manager?
BTW, excellent demo. I really like how with one line of code at the command line I was able to build a sample that worked on the first shot.
I guess README.MD, Startup.cs and config.json are not aligned.
This is what I was doing:
to fix it
"Tenant": "mytenant.onmicrosoft.com",
"AadInstance": "https://login.microsoftonline.com/{0}",
Authority = string.Format(CultureInfo.InvariantCulture, Configuration["AzureAd:AadInstance"], Configuration["AzureAD:Tenant"]),
now it works
Is it possible to add a bit more detail and maybe some screenshots to make it clearer what items we need to include in our config.json
file? For instance, I'm still a bit confused as to what the Tenant is and how to put that into the config.
Some of the code still rely on excluding kproj
(xproj
now).
The sample still rely on beta6
. This should be updated to rc1-final
.
Updates to RTM after that would only be minor.
Sign in
Sorry, but we’re having trouble signing you in.
AADSTS50011: The reply url specified in the request does not match the reply urls configured for the application: '3914dcdd-7a77-48d2-9219-b0eeec2e751e'.
I need to integrate AzureAD into an existing mvc application with Individual Accounts. Currently, Identity is used to manage the accounts and is configured in ConfigureServices(IServiceCollection services)
as follows:
public void ConfigureServices(IServiceCollection services) {
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<SampleDbContext>()
.AddDefaultTokenProviders();
}
If I try to add AzureAdOpenIdConnect
, I get an endless loop after signing in.
public void ConfigureServices(IServiceCollection services) {
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<SampleDbContext>()
.AddDefaultTokenProviders();
services.AddAuthentication(options => {
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddAzureAdOpenIdConnect(configureOptions)
.AddCookie();
}
I know that in order to make this work, I need to somehow wire AzureAD to generate an external login cookie, which I can then use in the callback to create a new user. However, all of the controller functionality used in the OpenIdConnect middleware is black-boxed. Is there a simple way to override the signin-oidc action to call the userManager and check if the client exists and if not create one, then sign in the user using the local account cookie and go from there?
Any help would be greatly appreciated!
I'm trying to get an integration test going for an API with authentication. Because some API functions call other API's on behalf of the user and this allows us to test everything before publishing.
The problem is I keep getting a 302 redirect even though I pass the token in the header. I'm not familiar with OpenID so perhaps I'm filling in the wrong header(s)? I've pretty much copy pasted the Startup from the sample. Can you please point me in the right direction?
FYI everything works without the AuthorizeAttribute on my controller.
public class Startup
{
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddOpenIdConnect(options =>
{
options.Authority = "hidden";
options.ClientId = "hidden";
options.CallbackPath = "/signin-oidc";
options.RequireHttpsMetadata = false;
options.UseTokenLifetime = true;
})
.AddCookie();
}
}
[TestClass]
public class Tests
{
[TestMethod]
public void Test()
{
// Get access token for API.
var httpClient = new HttpClient();
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("resource", "hidden"),
new KeyValuePair<string, string>("client_secret", "hidden"),
new KeyValuePair<string, string>("username", "hidden"),
new KeyValuePair<string, string>("password", "hidden"),
new KeyValuePair<string, string>("client_id", "hidden"),
new KeyValuePair<string, string>("grant_type", "password")
})
var result = httpClient.PostAsync(new Uri("https://login.microsoftonline.com/hidden.onmicrosoft.com/oauth2/token", formContent).Result;
var content = result.Content.ReadAsStringAsync().Result;
var accessToken = JObject.Parse(content)["access_token"].ToString();
// Create client calling the API.
var builder = new WebHostBuilder()
.UseStartup<Startup>();
var testServer = new TestServer(builder);
var client = testServer.CreateClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accToken);
var response = client.GetAsync("/hidden").Result; // Receiving a 302 redirect
var content = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(content);
Assert.IsTrue(response.IsSuccessStatusCode);
}
}
Hi, I am using Azure ad with .net core 2.0. I want to session timeout after 1 hour. But its not working.
I used session with cookie. Please help me.
` services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(10);
});
services.AddMvc();
// Add Authentication services.
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
// Configure the OWIN pipeline to use cookie auth.
// Configure the OWIN pipeline to use OpenID Connect auth.
.AddOpenIdConnect(option =>
{
option.UseTokenLifetime = true;
option.ClientId = Configuration["AzureAD:ClientId"];
option.Authority = String.Format(Configuration["AzureAd:AadInstance"], Configuration["AzureAd:Tenant"]);
option.SignedOutRedirectUri = Configuration["AzureAd:PostLogoutRedirectUri"];
option.Events = new OpenIdConnectEvents
{
OnRemoteFailure = OnAuthenticationFailed,
// OnTicketReceived = OnTicketReceived
};
}).AddCookie(options =>
{
options.ExpireTimeSpan = TimeSpan.FromSeconds(10);
options.LoginPath = "/Account/LogIn";
options.LogoutPath = "/Account/LogOff";
options.SlidingExpiration = false;
options.Cookie = new CookieBuilder
{
Name = "LeadsConnect",
Expiration = TimeSpan.FromSeconds(10),
};
});`
Would it be possible to show how to test this project?
I cloned this app and did the registration in Azure App Regsitration and everything works fine locally(I get the prompt to sign in). However when I publish this to Azure and access the website it shows the page - "Hey App developers...".
I also added the address of the newly created azure website to the Redirect_urls but it still doesnt work.
Any help here would be highly appreciated. Thanks!
I tried to implement this sample in .net core 2.1. At first it looks like it is working, it is redirecting me to the login page of azure AD of my company. But after loggin in I can see that the browser is looping from my application to azure ad and back, until after a while it just fails with a "bad request - headers too long".
Do you know of this issue and do you have any suggestions?
https://stackoverflow.com/questions/45742034/asp-net-core-2-0-argumentexception-options-clientid-must-be-provided
proper action is to change properties of input instead returning new object
Why is it poor? Because it claims:
"This sample shows how to build a .Net MVC web application that uses OpenID Connect to sign-in users from a single Azure Active Directory tenant, using the ASP.Net Core OpenID Connect middleware."
What it actually does is guide you through how to fill out the forms on Azure to create a new AAD application, and then copy/paste a few pieces of data into the sample application.
What it should do instead, is explain all of the deltas between a plain ASP.NET Core web app, and the version modified to support AAD. Even if it doesn't explain why you copy/paste code into specific parts, at least it would help folks. Folks come to the article not because they want to develop the WebApp-OpenIdConnect-DotNet application, but because they want to take their existing app and modify it to use AAD. So give us the information we need to complete that task.
Please and thanks.
Hi,
I'm having trouble getting the OpenID Challenge to work when using this sample. In my scenario I'm already signed in, but I want to issue a new OpenID Connect challenge. This is needed for example in cases where the ADAL token cache is empty while the user presents a valid cookie from a previous session. In those cases, a challenge should redirect the user to the auth endpoint, resulting in a new auth token to be presented to the app.
However, I don't seem to get this working: I'm being redirected to the Access Denied URL as configured in the cookie middleware. What am I doing wrong?
Thanks in advance for any nudge in the right direction.
How to you get Azure b2c edit profile to work?
I have tried the code below and it always redirects to forbidden.
var authenticationProperties = new AuthenticationProperties { RedirectUri = "/" };
await HttpContext.Authentication.ChallengeAsync(Startup.EditPolicyId.ToLower(), authenticationProperties);
This isn't necessarily a problem but just wanted to point out that AzureADAuthenticationBuilderExtensions.AddAzureAd is now AzureADAuthenticationBuilderExtensions.AddAzureAD (uppercase) in .NET Core 2.1. Took me a couple hours to figure out why .AddAzureAd wasn't recognized in my 2.1 project.
Does not work after all the work that went into AAD. Compiled successfully, followed instructions successfully to enter AAD tenant and clientId in config json. When I run it from Visual Studio, following error comes up.
This site can’t be reached
localhost refused to connect.
I don't know where to begin to troubleshoot this. Can you help? I really want this to work.
Sign in
Sorry, but we’re having trouble signing you in.
AADSTS50011: The reply address 'http://localhost:55643/signin-oidc' does not match the reply addresses configured for the application: 'd8e54159-61d2-4956-adad-cd7160824bb4'. More details: not specified
After hosting the given sample code by configuring the AAD, the normal authentication flow is working fine, when we type the URL in the browser window directly.
But, When we open the application URL from the Microsoft Word, getting the exception: Correlation failed.
Below are the steps to reproduce the issue:
Raw Exception Details:
System.Exception: Correlation failed.
at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Session.SessionMiddleware.d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Session.SessionMiddleware.d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.d__7.MoveNext()
I followed your example and works fine the only difference is that the controller where I want to login with Azure AD instead of [Authorize] I added: [Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)]. But all works good. The scenario is: use Azure AD to login only for a specific section of the site and ASP.NET Core 2.0 Identity for the rest of the site.
When I go to my controller I am redirect to Azure AD log in and redirected back to the application. All good here, User.Identity.IsAuthenticated is true, claims are present, etc. Works fine. if then I am navigating to another controller that is not using any [Authorize] attribute then User.Identity.IsAuthenticated is false and no claims are present. So basically I am navigating to the controller after I login with AD so I assume the Identity should be there. Am I doing something wrong?
I tried the sample but it fails to run in Visual Studio 2015 Update 3.
I cloned the code, ran solution file and hit F5. This should start IIS Express and server the https://localhost:44353/
website. Visual Studio will display the error message instead.
---------------------------
Microsoft Visual Studio
---------------------------
An error occurred attempting to determine the process id of dotnet.exe which is hosting your application. One or more errors occurred.
---------------------------
OK
---------------------------
How is the sample supposed to be run locally?
Trying to run this application I get the following error:
"An error occurred attempting to determine the process id of dotnet.exe which is hosting your application. One or more errors occurred."
To get [Authorize]
to work properly, I had to enable options.AutomaticAuthentication
in app.UseOpenIdConnectAuthentication(options => { ... });
. Otherwise, I would just get an immediate empty 401 response. Is this correct approach? If so, can you update the sample to indicate this? If not, can you explain what the proper approach is?
Also, there is a SO question referring to this.
Thanks!
I can see, this sample does not uses the ClientSecret from AzureAdOptions. Few other samples, for example this one, uses ClientSecert. What is the difference here?
I have changed the reply address in the config.json , have also cleaned the solution and rebuilt. But I cannot shake this error.
Additional technical information:
Correlation ID: 465125a3-feb6-4ce2-9b2a-8313d16d5c03
Timestamp: 2017-05-12 16:59:48Z
AADSTS50011: The reply address 'https://localhost:44353/signin-oidc' does not match the reply addresses configured for the application: 'dc695b2d-b6d5-47f5-bdfa-eb7daf7a1cbd'. More details: not specified
Any idea?
Thanks
Do:
git clone https://github.com/Azure-Samples/active-directory-dotnet-webapp-webapi-multitenant-openidconnect-aspnetcore.git
Open sln:
C:\github\azureadsamples\active-directory-webapp-webapi-multitenant-openidconnect-aspnetcore\TodoListWebApp\TodoListWebApp.xproj : error : The imported project "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\DotNet\Microsoft.DotNet.Props" was not found. Confirm that the path in the declaration is correct, and that the file exists on disk. C:\github\azureadsamples\active-directory-webapp-webapi-multitenant-openidconnect-aspnetcore\TodoListWebApp\TodoListWebApp.xproj
The two links under: 'Getting started is simple! To run this sample you will need:'
Don't offer clear instruction on what to do.
The first link (.NET Core & .NET Core SDK RC2 releases) - the user has a multiple of choices.
The second link (ASP.NET Core RC2 release) - is simply informational an it is not clear what the purpose is.
How should I modify your ASP.NET Core 2 sample in order to enable CORS scenario?
Currently, the sample redirects to backend's domain root.
E.g. I redirect from localhost/index.html to www.myapp.net/account/login -> redirects to Identity Provider's login -> redirects to www.myapp.net
When I modify the sample with return url, the frontend running on different domain is not authenticated:
[HttpGet("login")]
public async Task Login(string returnUrl = null)
{
await HttpContext.ChallengeAsync(
OpenIdConnectDefaults.AuthenticationScheme,
new AuthenticationProperties { RedirectUri = returnUrl });
}
E.g. I redirect from localhost/index.html to www.myapp.net/account/login?returnUrl=http://localhost/index.html -> redirects to Identity Provider's login -> redirects back to localhost/index.html -> request made from localhost are still not authenticated
Could you update this sample with GraphApi please?
Also in the mean time, how do we get the assign roles of the user
Also how do we assign role to a user, neither by portal first and then by code.
Thank you very much in advance :-)
Using the exact code found in the sample I'm getting the following error when calling a resource on behalf of the user calling the API after an hour: "Failed to acquire token silently as no token was found in the cache. Call method AcquireToken".
It works for an hour but when it comes to refreshing the token it fails. I'm trying to access an azure analysis services cube through an API request.
How I'm getting the OBO token:
public static async Task<string> AcquireOnBehalfOfToken(
string resourceId,
string userObjectId,
ISession session)
{
AuthenticationContext authContext = new AuthenticationContext(AzureAdOptions.Settings.Authority, new NaiveSessionCache(userObjectId, session));
ClientCredential credential = new ClientCredential(AzureAdOptions.Settings.ClientId, AzureAdOptions.Settings.ClientSecret);
var result = await authContext.AcquireTokenSilentAsync(resourceId, credential, new UserIdentifier(userObjectId, UserIdentifierType.UniqueId));
var onBehalfOfToken = result.AccessToken;
return onBehalfOfToken;
}
My Startup.cs:
public class Startup
{
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseSession(); // Needs to be app.UseAuthentication() and app.UseMvc() otherwise you will get an exception "Session has not been configured for this application or request."
app.UseAuthentication();
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddAzureAd(options =>
{
Configuration.Bind("AzureAd", options);
AzureAdOptions.Settings = options;
})
.AddCookie();
services.AddSession();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1).AddSessionStateTempDataProvider();
}
}
use the aspnet_core_2_0 branch
Look at the readme
Expected:
It explains the ASP.NET Core 2.0 code
Actual
It's still about ASP.NET Core 1.x
Tried to follow the steps in VS 2015 RC and it seems to be missing some steps with there. Can this be updated for the RC?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.