Coder Social home page Coder Social logo

azuread / microsoft-identity-web Goto Github PK

View Code? Open in Web Editor NEW
654.0 231.0 201.0 8.06 MB

Helps creating protected web apps and web APIs with Microsoft identity platform and Azure AD B2C

License: MIT License

C# 80.89% HTML 5.79% CSS 1.32% JavaScript 8.90% PowerShell 1.66% Batchfile 1.44% ASP.NET 0.01%
asp-net-core microsoft-identity-platform aadv2 authentication

microsoft-identity-web's Introduction

Microsoft Identity Web

Microsoft Identity Web is a library which contains a set of reusable classes used in conjunction with ASP.NET Core for integrating with the Microsoft identity platform (formerly Azure AD v2.0 endpoint) and AAD B2C.

This library is for specific usage with:

Quick links:

Conceptual documentation Getting Started Reference documentation Sample Code Web App Sample Code Web API Support

Nuget package

NuGet

Build Status

Build Status

Release notes, roadmap and SLA

Release notes and roadmap

The Microsoft Identity Web roadmap is available from Roadmap in the Wiki pages, along with release notes.

Support SLA

  • Major versions are supported for twelve months after the release of the next major version.
  • Minor versions older than N-1 are not supported.

    Minor versions are bugfixes or features with non-breaking (additive) API changes. It is expected apps can upgrade. Therefore, we will not patch old minor versions of the library. You should also confirm, in issue repros, that you are using the latest minor version before the Microsoft Identity Web team spends time investigating an issue.

Using Microsoft Identity Web

Where do I file issues

This is the correct repo to file issues.

Community Help and Support

If you find a bug or have a feature or documentation request, please raise the issue on GitHub Issues.

We use Stack Overflow with the community to provide support, using the tags web-app, web-api, asp.net-core, microsoft-identity-web. We highly recommend you ask your questions on Stack Overflow first and browse existing issues to see if someone has asked your question before.

To provide a recommendation, visit our User Voice page.

Contribute

We enthusiastically welcome contributions and feedback. You can clone the repo and start contributing now. Read our Contribution Guide for more information.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

Security Library

This library controls how users sign-in and access services. We recommend you always take the latest version of our library in your app when possible. We use semantic versioning so you can control the risk associated with updating your app. As an example, always downloading the latest minor version number (e.g. x.y.x) ensures you get the latest security and feature enhancements, but our API surface remains the same. You can always see the latest version and release notes under the Releases tab of GitHub.

Security Reporting

If you find a security issue with our libraries or services, please report it to [email protected] with as much detail as possible. Your submission may be eligible for a bounty through the Microsoft Bounty program. Please do not post security issues to GitHub Issues or any other public site. We will contact you shortly upon receiving the information. We encourage you to get notifications of when security incidents occur by visiting this page and subscribing to Security Advisory Alerts.

Trademarks.

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.

Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License (the "License").

microsoft-identity-web's People

Contributors

adyle5 avatar baywet avatar bgavrilms avatar brentschmaltz avatar dependabot[bot] avatar durandt avatar fupingfranco avatar hajekj avatar jennyf19 avatar jmprieur avatar joshlozensky avatar keegan-caruso avatar kellyyangsong avatar mattkotsenas avatar matyri avatar microsoftopensource avatar pmaytak avatar robi26 avatar saurabhmsft avatar sayedihashimi avatar sebader avatar shama-k avatar shazwazza avatar sruke avatar threesevenths avatar tiagobrenck avatar timclyburn avatar trwalke avatar twsouthwick avatar westin-m avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

microsoft-identity-web's Issues

[Bug] Calling graph api on behalf of throws MsalUiRequiredException

Which Version of Microsoft Identity Web are you using ?
Note that to get help, you need to run the latest version.

Where is the issue?

  • Web App
    • Sign-in users
    • Sign-in users and call web APIs
  • Web API
    • Protected web APIs (Validating tokens)
    • Protected web APIs (Validating scopes)
    • Protected web APIs call downstream web APIs
  • Token cache serialization
    • [X ] In Memory caches
    • Session caches
    • Distributed caches

Other? - please describe;

Is this a new or existing app?
c. This is a new app or experiment

Repro
The application is pretty simple, you must be authenticated against AAD.
The default route will do a call to the graph api.

GraphUser = await _graphServiceClient.Me.Request().GetAsync();

Here is my Startup.cs

            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

            services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
                .AddSignIn("AzureAd", Configuration, options => Configuration.Bind("AzureAd", options));

            services.AddWebAppCallsProtectedWebApi(Configuration, Configuration.GetSection("GraphApi:Scopes").Get<string[]>())
                    .AddInMemoryTokenCaches();

In Visual Studio 2019, hit CTRL+F5 (run without debugging) everything works fine.
Keep this tab open, go back to VS2019 and hit F5 (run with attached debugger) it throws.

Expected behavior
Get result from the graph api

Actual behavior
The applciation throws MsalUiRequiredException

MSAL.NetCore.4.8.2.0.MsalUiRequiredException:
        ErrorCode: user_null

MsalUiRequiredException: No account or login hint was passed to the AcquireTokenSilent call.

    Microsoft.Identity.Client.AcquireTokenSilentParameterBuilder.Validate()
    Microsoft.Identity.Client.AbstractAcquireTokenParameterBuilder<T>.ValidateAndCalculateApiId()
    Microsoft.Identity.Client.AbstractClientAppBaseAcquireTokenParameterBuilder<T>.ExecuteAsync(CancellationToken cancellationToken)
    Microsoft.Identity.Client.AbstractAcquireTokenParameterBuilder<T>.ExecuteAsync()
    Microsoft.Identity.Web.TokenAcquisition.GetAccessTokenOnBehalfOfUserFromCacheAsync(IConfidentialClientApplication application, IAccount account, IEnumerable<string> scopes, string tenant) in TokenAcquisition.cs

                    result = await application

Microsoft.Identity.Web.TokenAcquisition.GetAccessTokenOnBehalfOfUserFromCacheAsync(IConfidentialClientApplication application, ClaimsPrincipal claimsPrincipal, IEnumerable<string> scopes, string tenant) in TokenAcquisition.cs

                return await GetAccessTokenOnBehalfOfUserFromCacheAsync(application, account, scopes, tenant).ConfigureAwait(false);

Microsoft.Identity.Web.TokenAcquisition.GetAccessTokenForUserAsync(IEnumerable<string> scopes, string tenant) in TokenAcquisition.cs

                    accessToken = await GetAccessTokenOnBehalfOfUserFromCacheAsync(_application, CurrentHttpContext.User, scopes, tenant)

Microsoft.Identity.Web.TokenAcquisition.GetAccessTokenForUserAsync(IEnumerable<string> scopes, string tenant) in TokenAcquisition.cs

                        throw;

MyProject.ThirdParties.GraphApi.GraphApiAuthenticationProvider.AuthenticateRequestAsync(HttpRequestMessage request) in GraphApiAuthenticationProvider.cs

                string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(_configuration.Scopes);

Microsoft.Graph.AuthenticationHandler.SendAsync(HttpRequestMessage httpRequestMessage, CancellationToken cancellationToken)
System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task<HttpResponseMessage> sendTask, HttpRequestMessage request, CancellationTokenSource cts, bool disposeCts)
Microsoft.Graph.HttpProvider.SendRequestAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)

Possible Solution
Closing all browsers fix the issue until you do again CTRL+F5 then F5 in VS2019

[Investigate] ADFS and lack of TenantId in TokenAcquisition class

@bgavrilMS reminds us that ADFS does not have a tenant_id, so how will that impact GetAccessTokenOnBehalfOfUserFromCache() in the TokenAcquisition class, around line 459

else if (!string.IsNullOrWhiteSpace(tenant))
{
    // Acquire an access token as another AAD authority
    string authority = application.Authority.Replace(new Uri(application.Authority).PathAndQuery, $"/{tenant}/");
    result = await application
        .AcquireTokenSilent(scopes.Except(_scopesRequestedByMsal), account)
        .WithAuthority(authority)
        .ExecuteAsync()
        .ConfigureAwait(false);
    return result.AccessToken;
}
else
{
    result = await application
        .AcquireTokenSilent(scopes.Except(_scopesRequestedByMsal), account)
        .ExecuteAsync()
        .ConfigureAwait(false);
    return result.AccessToken;
}

[Bug] key _AppTokenCache does not contain ClientId if not set in MicrosoftIdentityOptionss

If the ClientId is not set in MicrosoftIdentityOptions, and only in the ConfidentialClientApplicationOptions, then the cache key for the app cache does not contain the Client_id.

Ex:

 services.AddTransient(
_provider => Options.Create(new MicrosoftIdentityOptions
     {
          Authority = TestConstants.AuthorityCommonTenant,
          //ClientId = TestConstants.ConfidentialClientId,
     }));
services.AddTransient(
_provider => Options.Create(new ConfidentialClientApplicationOptions
    {
         Instance = TestConstants.AadInstance,
         TenantId = TestConstants.ConfidentialClientLabTenant,
         ClientId = TestConstants.ConfidentialClientId,
         ClientSecret = _ccaSecret
    }
));

the above will give this key : _AppTokenCache

But this:

 services.AddTransient(
_provider => Options.Create(new MicrosoftIdentityOptions
     {
          Authority = TestConstants.AuthorityCommonTenant,
          ClientId = TestConstants.ConfidentialClientId,
     }));
services.AddTransient(
_provider => Options.Create(new ConfidentialClientApplicationOptions
    {
         Instance = TestConstants.AadInstance,
         TenantId = TestConstants.ConfidentialClientLabTenant,
         ClientSecret = _ccaSecret
    }
));

will give d6921528-eb23-4423-a023-99b1b60f6285_AppTokenCache

Should clear session auth cookie if cache is missing account

from @onovotny and copied from Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2#240

In the Microsoft.Identity.Web library, the system should automatically clear (RejectPrincipal()) the auth cookie if the corresponding account entry is missing from the token cache. This can happen if the cache expired, if it was a memory cache and the server bounced, etc.

The issue is that the system is now in an inconsistent state, where the user is considered logged-in, but any operations to call API's won't succeed because there's no token cache, no refresh token, etc.

I've worked around this here: https://github.com/dotnet-foundation/membership

In order to do so, I had to make some changes to ITokenAquisition and the MsalAbstractCacheProvider's GetCacheKey method.

ITokenAcquisition needed a method to check for a user's token cache:
https://github.com/dotnet-foundation/membership/blob/97b75e30e50aab76bfa5a21f1ab88bf31ae66da4/Microsoft.Identity.Web/TokenAcquisition.cs#L406-L426

In there, it takes the CookieValidatePrincipalContext to get the incoming ClaimsPrincpal as HtttpContext.User is not yet set at that point. It stores it in the HttpContext.Items via the StoreCookieValidatePrincipalContext extension method (used later by the GetCacheKey method so it can derive the appropriate key):
https://github.com/dotnet-foundation/membership/blob/97b75e30e50aab76bfa5a21f1ab88bf31ae66da4/Microsoft.Identity.Web/TokenCacheProviders/MsalAbstractTokenCacheProvider.cs#L68-L69

Finally, the CookieAuthenticationOptions needs to be configured to check for and reject the incoming principal (this could/should be moved into the main IdentityPlatform AddMsal extension methods):
https://github.com/dotnet-foundation/membership/blob/97b75e30e50aab76bfa5a21f1ab88bf31ae66da4/Membership/Startup.cs#L110-L123

I can submit these changes as PR if you're in agreement with these changes.

ITokenAcquisition needs to have a member AcquireTokenForApp

ITokenAcquisition needs to support the daemon scenario.
proposing to add a new method:

string AcquireTokenForApp(IEnumerable<string> scopes)

we might want to see if we want to leverate Managed identity, in the case of web apps/apis hosted in Azure or on the dev box

Call user_info endpoint for AAD guest scenarios

Why?

TokenAcquistion.cs has hacks to try to guess guest scenarios. In the case of guest scenarios the home tenant ID, home object id is different from the tenantID, object ID which are provided in the IDToken. But we don't have today the home tid/oid information, and therefore we don't know that this is a guest user.
MSAL.NET uses the home tenant information, and therefore in the guest scenarios we don't find find the tokens in the cache today (I believe UniqueObjectIdentifier)

// Special case for guest users as the Guest oid / tenant id are not surfaced.
// B2C should not follow this logic since loginHint is not present
if (!_microsoftIdentityOptions.IsB2C && account == null)
{
if (loginHint == null)
throw new ArgumentNullException(nameof(loginHint));
var accounts = await application.GetAccountsAsync().ConfigureAwait(false);
account = accounts.FirstOrDefault(a => a.Username == loginHint);
}

and

// Workaround for the guest account
if (account == null)
{
var accounts = await app.GetAccountsAsync().ConfigureAwait(false);
account = accounts.FirstOrDefault(a => a.Username == user.GetLoginHint());
}
if (account != null)
{
await app.RemoveAsync(account).ConfigureAwait(false);
_tokenCacheProvider?.ClearAsync().ConfigureAwait(false);
}

The hypothesis is that we'd want to call the User info endpoint not only for B2C, but also AAD, and get the home tenant ID, home iod, instead of the hack.

What ?

  • Like we do w/B2C, call the user_info endpoint for AAD guest scenarios. Today we test for B2C. We probably want to do the same or similar for AAD.

    if (microsoftIdentityOptions.IsB2C)
    {
    context.ProtocolMessage.SetParameter("client_info", "1");
    // When a new Challenge is returned using any B2C user flow different than susi, we must change
    // the ProtocolMessage.IssuerAddress to the desired user flow otherwise the redirect would use the susi user flow
    await b2cOidcHandlers.OnRedirectToIdentityProvider(context).ConfigureAwait(false);
    }

  • probably (to be checked) change the GetMsalId method to use the home tenant information?

public static string GetMsalAccountId(this ClaimsPrincipal claimsPrincipal)

  • if this is successful, remove the hacks?

How to test?

Otherwise we could add an hotmail account in a test tenant. Alternatively the identity lab will have guest accounts.

[Feature Request] Enable several JWE decrypt keys to help handling certificate rotations

Is your feature request related to a problem? Please describe.
We need to help partners using JWE to handle certificate rotation. Today,

public static AuthenticationBuilder AddProtectedWebApi(

takes one certificate, which is used as an entry to TokenValidationParameters.

if (tokenDecryptionCertificate != null)
{
options.TokenValidationParameters.TokenDecryptionKey = new X509SecurityKey(tokenDecryptionCertificate);
}

Describe the solution you'd like
When the certificates are rotated, we'd like to pass several certificates and:

  • either try to decryp with one, and if this does not work try the other
  • or implement a TokenDecryptionKeyResolver that inspects the JWT token header for the encrypt cert thumbprint and then return the corresponding encrypt cert for decrypting the token.

See also https://github.com/AzureAD/microsoft-identity-web/wiki/Spec-certificates

See also SNI: AzureAD/microsoft-authentication-library-for-python#60

[Feature Request] Leverage the ASP.NET Core IHttpClientFactory

This issue is for a: (mark with an x)

- [ ] bug report -> please search issues before submitting
- [x ] feature request
- [ ] documentation issue or request
- [ ] regression (a behavior that used to work and stopped in a new release)

Why?

Architectural guidance recommand to Use IHttpClientFactory to implement resilient HTTP requests.

ASP.NET Core IHttpClientFactory manages the pooling and lifetime of underlying HttpClientMessageHandler instances, which avoids port exhaustion and common DNS (Domain Name System) problems that occur when manually managing HttpClient lifetimes.
It also allows for configurable logging experience (via ILogger) for all requests sent through clients created by the factory.

Today, when instanciating a IConfidentialClientApplication in

if (_microsoftIdentityOptions.IsB2C)
{
authority = $"{ _applicationOptions.Instance}tfp/{_microsoftIdentityOptions.Domain}/{_microsoftIdentityOptions.DefaultUserFlow}";
app = ConfidentialClientApplicationBuilder
.CreateWithApplicationOptions(_applicationOptions)
.WithRedirectUri(currentUri)
.WithB2CAuthority(authority)
.Build();
}
else
{
authority = $"{ _applicationOptions.Instance}{_applicationOptions.TenantId}/";
app = ConfidentialClientApplicationBuilder
.CreateWithApplicationOptions(_applicationOptions)
.WithRedirectUri(currentUri)
.WithAuthority(authority)
.Build();
}

we leave it to MSAL.NET to manage the HttpClient

Possible design

For the moment, we could have the following design

  1. Add a new parameter httpClientFactory of type IHttpClientFactory in the constructor of TokenAcquisition:
    public TokenAcquisition(
    IMsalTokenCacheProvider tokenCacheProvider,
    IHttpContextAccessor httpContextAccessor,
    IOptions<MicrosoftIdentityOptions> microsoftIdentityOptions,
    IOptions<ConfidentialClientApplicationOptions> applicationOptions,
    ILogger<TokenAcquisition> logger)
    so that an HttpClientFactor can be injected by dependency injection. Also add a corresponding property to TokenAcquisition
  2. Add a new internal class (for instance MsalAspNetCoreHttpClientFactory) implementing IMsalHttpClientFactory and having a constructor with an ASP.NET Core IHttpClientFactory, and which CreateClient() method would just delegate to IHttpClientFactory
  3. When building MSAL.NET confidential client application, use the .WithHttpClientFactory(httpClientFactory) modifyer and instanciate a MsalAspNetCoreHttpClientFactory from the httpClientFactory property
  4. In AddWebAppCallsWebApi and AddProtectedWebApiCallsWebApi, add a service: services.AddHttpClient();

Possible future improvement

I don't think we need to use Named clients ?

Copied from Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2#267

[Feature Request] Add a ASP.NET middleware that ensures user has an access token in the cache before calling controller actions.

The current approach for refreshing an access token is using the AuthorizeForScopes attribute on controller actions. We faced some issues while using this approach. Consider following controller action. DoSomethingAndSendNotification method updates the state in the database and then sends a notification via a call to Microsoft Graph API in the SendNotification function.

[AuthorizeForScopes(Scopes = new[] {Constants.ScopeUserRead})]
        public async Task<IActionResult> DoSomethingAndSendNotification(string username)
        {
            var orderId = _orderService.RegisterOrder(username);

            var accessToken =
                await tokenAcquisition.GetAccessTokenForUserAsync(new[] {Constants.ScopeUserRead});

            _notificationService.SendNotification(username, accessToken);
            return View();
        }

The first issue we faced was with token caching and app restarts. We used in memory token caching. So users authenticated normally with app and got their token added to the cache. Then when we did an app restart (due to updates) we come to the situation when user's browser has a valid authentication cookie but the backed cache doesn't have an access token in the cache. So when the user presses a button and calls the DoSomethingAndSendNotification method again an exception will be raised from GetAccessTokenForUserAsync method. AuthorizeForScopes attribute handles the exception and redirects the user to AAD for authentication flow. When the user authenticates she is redirected back and the DoSomethingAndSendNotification method is re-executed. Problem in this case is that is this sample _orderService.RegisterOrder(username); method is called again and double order will be registered for the user.

To solve this we either needed to design orderService with a re-entrancy logic or we need to ensure that before the controller's action is called we somehow ensure that user has an access token in the cache. For that we implemented this ASP.NET middleware:

public class TokenSetterMiddleware
    {
        private readonly RequestDelegate _next;
        private ConfidentialClientApplicationOptions _applicationOptions;
        private readonly AzureADOptions _azureAdOptions;
        private readonly TokenSetterMiddlewareOptions _options;
        private readonly IMsalTokenCacheProvider _tokenCacheProvider;

        public TokenSetterMiddleware(RequestDelegate next, IConfiguration configuration, IOptions<TokenSetterMiddlewareOptions> options,
            IMsalTokenCacheProvider tokenCacheProvider)
        {
            _next = next;
            _options = options.Value;
            _tokenCacheProvider = tokenCacheProvider;
            _azureAdOptions = new AzureADOptions();
            configuration.Bind("AzureAD", _azureAdOptions);
            _applicationOptions = new ConfidentialClientApplicationOptions();
            configuration.Bind("AzureAD", _applicationOptions);
        }

        public async Task InvokeAsync(HttpContext context)
        {
            if (context.User.Identity.IsAuthenticated &&
                (context.Request.Path != _azureAdOptions.CallbackPath
                || context.Response.StatusCode != 302))
            { 
                var app = BuildConfidentialClientApplication(context, context.User);
                var user = await app.GetAccountAsync(context.User.GetMsalAccountId());

                if (user == null)
                {
                    //Workaround for Guest Users
                    var loginHint = context.User.GetLoginHint();
                    var accounts = await app.GetAccountsAsync();
                    user = accounts.FirstOrDefault(a => a.Username == loginHint);

                    if (user == null)
                    {
                        var properties = BuildAuthenticationPropertiesForIncrementalConsent(_options.Scopes, context);
                        await context.ChallengeAsync(properties);
                        return;
                    }
                    
                }
            }
            await _next(context);
        }

        private IConfidentialClientApplication BuildConfidentialClientApplication(HttpContext httpContext, ClaimsPrincipal claimsPrincipal)
        {
            var request = httpContext.Request;
            var azureAdOptions = _azureAdOptions;
            var applicationOptions = _applicationOptions;
            string currentUri = UriHelper.BuildAbsolute(
                request.Scheme,
                request.Host,
                request.PathBase,
                azureAdOptions.CallbackPath ?? string.Empty);

            string authority = $"{applicationOptions.Instance}{applicationOptions.TenantId}/";

            var app = ConfidentialClientApplicationBuilder
                .CreateWithApplicationOptions(applicationOptions)
                .WithRedirectUri(currentUri)
                .WithAuthority(authority)
                .Build();

            // Initialize token cache providers
            _tokenCacheProvider?.InitializeAsync(app.AppTokenCache);
            _tokenCacheProvider?.InitializeAsync(app.UserTokenCache);

            return app;
        }

        private AuthenticationProperties BuildAuthenticationPropertiesForIncrementalConsent(
            string[] scopes, HttpContext context)
        {
            var properties = new AuthenticationProperties();

            // Set the scopes, including the scopes that ADAL.NET / MASL.NET need for the Token cache
            string[] additionalBuildInScopes =
                {OidcConstants.ScopeOpenId, OidcConstants.ScopeOfflineAccess, OidcConstants.ScopeProfile};
            properties.SetParameter<ICollection<string>>(OpenIdConnectParameterNames.Scope,
                                                         scopes.Union(additionalBuildInScopes).ToList());

            // Attempts to set the login_hint to avoid the logged-in user to be presented with an account selection dialog
            var loginHint = context.User.GetLoginHint();
            if (!string.IsNullOrWhiteSpace(loginHint))
            {
                properties.SetParameter(OpenIdConnectParameterNames.LoginHint, loginHint);

                var domainHint = context.User.GetDomainHint();
                properties.SetParameter(OpenIdConnectParameterNames.DomainHint, domainHint);
            }

            return properties;
        }
    }

(Sorry for the code quality. Didn't have time for refactoring.)
I am curious what you think about this approach? Is this an acceptable solutions for product? Are that alternatives to the AuthorizeForScopes attribute?
Thanks.

[Bug] Protected API calls protected API: TokenAcquisition.GetAccessTokenForUserAsync throws null pointer exception

Which Version of Microsoft Identity Web are you using ?
Microsoft Identity Web 1.0.0-preview

Where is the issue?

  • Web App
    • Sign-in users
    • Sign-in users and call web APIs
  • Web API
    • Protected web APIs (Validating tokens)
    • Protected web APIs (Validating scopes)
    • Protected web APIs call downstream web APIs
  • Token cache serialization
    • In Memory caches
    • Session caches
    • Distributed caches

Other? - please describe;

Is this a new or existing app?
c. This is a new app or experiment

Repro
I have a SPA that calls a protected API that calls a downstream API. The problem is in the calling API.
I have generated NSwag client code for the downstream API that I inject a handler into - the handler code looks like this:

async override SendAsync (request, cancellationToken) {
  var token = await _tokenAcquisition.GetAccessTokenForUserAsync([ _config.Scope ]);
  request.Headers.Authorization = AuthenticationHeaderValue("Bearer", token);
  return await base.SendAsync(request, cancellationToken);
}

The projects (all 3 of them) are set up following the published API-calls-API scenarios. I have tested everything else independently working but when I try to chain them together, this bug occurs.

Expected behavior
Valid token is returned

Actual behavior
MSAL.NET throws null pointer exception, uncaught by this library

Additional context/ Logs / Screenshots
By the time the code gets to the handler, The token passed in is obtained by the SPA and passes authorization on the first API.

On calling GetAccessTokenForUserAsync the code eventually gets to the Web API flow in TokenAcquisition.cs

When executing this code, a null pointer exception is thrown by MSAL.NET's ClientCredentialHelper because ClientCredential.Thumbprint property getter throws an exception upon initialization, and that helper tries to reference it. You can see the problem from this screenshot (taken from TokenClient.cs)
Annotation 2020-03-24 212856

I am completely stuck and am at a loss of how to work around this problem.

I put the issue here because I found it while trying to use this library, but the issue may be a bug in MSAL.NET, so let me know if I should add it there as well.

No user scopes leads to error

from @onovotny and copied from Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2#241

If you want to use .AddMsal(), there's no way to do so without any user scopes. It might be needed for Application flows.

If you use new string[0] for the scopes parameter, it'll throw in the OnAuthorizationCodeReceived callback since options.Scope will be null:
await tokenAcquisition.AddAccountToCacheFromAuthorizationCodeAsync(context, options.Scope).ConfigureAwait(false);

Investigate if AuthorizeForScopes could use a Policy instead of an exception filter

Why?
Policies work independently of ASP.NET, or even Http. They work with SignalR..
The recommendation of the ASP.NET Core team is to not embed rules in a filters
Policies can be parametrized.

What?
AuthorizeForScopes might be be a Policy
(or not, this might not work, in which case Barry wants to know)

Resources
=> GitHub.com/blowdart=>old workshop.

copied from Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2#292

Add "Configuration" examples in README.md [Documentation]

Documentation Related To Component:

services.AddSignIn(Configuration) and services.AddProtectedWebApi(Configuration)

Please check those that apply

  • typo
  • documentation doesn't exist
  • documentation needs clarification
  • error(s) in example
  • needs example

Description Of The Issue

Please include examples of "Configuration" in AddSignIn and AddProtectedWebApi in the README.md.

[Feature Request] Detect and support Easy Auth

This issue is for a: (mark with an x)

- [ ] bug report -> please search issues before submitting
- [x ] feature request
- [ ] documentation issue or request
- [ ] regression (a behavior that used to work and stopped in a new release)

The issue was found for the following scenario:

Please add an 'x' for the scenario(s) where you found an issue

  1. Web app that signs in users
    1. [ x] with a work and school account in your organization: 1-WebApp-OIDC/1-1-MyOrg
    2. [ x] with any work and school account: /1-WebApp-OIDC/1-2-AnyOrg
    3. [ x] with any work or school account or Microsoft personal account: 1-WebApp-OIDC/1-3-AnyOrgOrPersonal
    4. [x ] with users in National or sovereign clouds 1-WebApp-OIDC/1-4-Sovereign
    5. with B2C users 1-WebApp-OIDC/1-5-B2C
  2. Web app that calls Microsoft Graph
    1. [ x] Calling graph with the Microsoft Graph SDK: 2-WebApp-graph-user/2-1-Call-MSGraph
    2. With specific token caches: 2-WebApp-graph-user/2-2-TokenCache
    3. Calling Microsoft Graph in national clouds: 2-WebApp-graph-user/2-4-Sovereign-Call-MSGraph
  3. Web app calling several APIs 3-WebApp-multi-APIs
  4. Web app calling your own Web API 4-WebApp-your-API
  5. Web app restricting users
    1. by Roles: 5-WebApp-AuthZ/5-1-Roles
    2. by Groups: 5-WebApp-AuthZ/5-2-Groups
  6. Deployment to Azure
  7. Other (please describe)

Repro-ing the issue

Repro steps

Enable AAD authentication with Easy Auth (on an App Service). See https://docs.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-auth-aad

Expected behavior

  • The Web App should sign-in the user that was authenticated with Easy Auth (by using the X-MS-TOKEN-AAD-ID-TOKEN, and possibly X-MS-TOKEN-PRINCIPAL-NAME
  • The Web App should be able to call any Web Apis from the refresh token provided by Easy Auth (using MSAL.NET AcquireTokenByRefreshToken)

Actual behavior

Does not work as 2 validations occur

Possible Solution

Additional context/ Error codes / Screenshots

Open question
How to validate the refresh token? we could validate the Access token and require both ...

Client assertion audience does not match Realm issuer with JWT assertion.

from @robgarrett and copied from Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2#213

Is it possible to use client assertion (JWT payload) instead of a client secret in the authorization code grant, with a Microsoft Personal Account?

I've tried the flow manually (outside of MSAL framework) using the COMMON endpoint as the JWT audience and get an error "client assertion audience does not match Realm issuer".

Curious if anyone has this working.

Enable AuthorizeForScopes to be applied to a controller (was Exception thrown: 'Microsoft.Identity.Client.MsalUiRequiredException')

from @jasonshave and copied from Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2#216

This issue is for a: (mark with an x)

- [X ] bug report -> please search issues before submitting
- [ ] feature request
- [ ] documentation issue or request
- [ ] regression (a behavior that used to work and stopped in a new release)

The issue was found for the following scenario:

Please add an 'x' for the scenario(s) where you found an issue

  1. Web app that signs in users
    1. [X ] with a work and school account in your organization: 1-WebApp-OIDC/1-1-MyOrg
    2. with any work and school account: /1-WebApp-OIDC/1-2-AnyOrg
    3. with any work or school account or Microsoft personal account: 1-WebApp-OIDC/1-3-AnyOrgOrPersonal
    4. with users in National or sovereign clouds 1-WebApp-OIDC/1-4-Sovereign
    5. with B2C users 1-WebApp-OIDC/1-5-B2C
  2. Web app that calls Microsoft Graph
    1. [X ] Calling graph with the Microsoft Graph SDK: 2-WebApp-graph-user/2-1-Call-MSGraph
    2. With specific token caches: 2-WebApp-graph-user/2-2-TokenCache
    3. Calling Microsoft Graph in national clouds: 2-WebApp-graph-user/2-4-Sovereign-Call-MSGraph
  3. Web app calling several APIs 3-WebApp-multi-APIs
  4. Web app calling your own Web API 4-WebApp-your-API
  5. Web app restricting users
    1. by Roles: 5-WebApp-AuthZ/5-1-Roles
    2. by Groups: 5-WebApp-AuthZ/5-2-Groups
  6. Deployment to Azure
  7. Other (please describe)

Repro-ing the issue

Repro steps

  1. Start the website in debug mode using VS2019 and observe the execution work correctly when pulling the user's photo from MS Graph.
  2. Stop the website.
  3. Start the debug session again and observe the call to MS Graph fail.

Expected behavior
I would expect the website to retrieve a previously obtained, and stored, token to be used to authenticate to the MS Graph.

Actual behavior
An exception is thrown in Microsoft.Identity.Web when trying to obtain a token:

Message="No account or login hint was passed to the AcquireTokenSilent call."

While executing:

private async Task<string> GetAccessTokenOnBehalfOfUserAsync(
            IConfidentialClientApplication application,
            string accountIdentifier,
            IEnumerable<string> scopes,
            string loginHint,
            string tenant)

The code falls into: IAccount account = await application.GetAccountAsync(accountIdentifier).ConfigureAwait(false);

Which returns null. LoginHint is observed with the user's UPN just fine (from line 383).

Next, it executes: var accounts = await application.GetAccountsAsync().ConfigureAwait(false);

...and falls into private async Task OnBeforeAccessAsync(TokenCacheNotificationArgs args)

This appears to try and read a cache of some sort. The cacheKey from line 88 in MsalAbstractTokenCacheProvider is populated, but then the following line returns null:
byte[] tokenCacheBytes = await ReadCacheBytesAsync(cacheKey).ConfigureAwait(false);

Next, line 399 executes and the authority variable is populated with the "login.microsoftonline.com/{tenantID}" value.

The application throws at line 400 which is:

result = await application
                    .AcquireTokenSilent(scopes.Except(_scopesRequestedByMsalNet), account)
                    .WithAuthority(authority)
                    .ExecuteAsync()
                    .ConfigureAwait(false);

Possible Solution
I used a previous version which had an attribute class for [MsalUiRequiredExceptionFilter(Scopes = new[] { ScopeConstants.ScopeUserRead })] which helped this issue I had previously. With the latest version things have changed quite a bit so I'm not sure if that old attribute extension class is even valid anymore. I did try adding it back to the project and decorated one of my controllers with it but it doesn't seem to help.

If I clear out the browser cache/cookies, I can get authenticated just fine. It's only on the subsequent attempts is when it fails.

Additional context/ Error codes / Screenshots

Any log messages given by the failure

Add any other context about the problem here, such as logs.

OS and Version?

Windows 10

Versions

ASP.NET Core 2.2

Attempting to troubleshooting yourself:

Mention any other details that might be useful

Production-readiness & Issues

From @sujayvsarma and copied from: Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2#254

First of all, kudos to every developer that worked on writing these samples and the Microsoft.Identity.Web codebase. You have done a great job at trying to navigate the maze that is ADAL + MSAL and tried to make things as easy as possible.

BUT...

Since you are talking about making Microsoft.Identity.Web "production grade" by making it available as a NuGet package, I don't think it is ready, not by a country mile. Here are some of the problems inherent in the codebase:

1. Library cannot handle multi-tenant + multi-api scenario
So, the "Multi-tenant" samples and code on their own work quite well. And the "Multi-API" samples and their code work on their own quite well. BUT, if you want to do multi-tenant + multi-API in one app, that does not work at all. Quite a lot of work arounds and ifs and buts need to be added to make all of that work.

Simple repro -- use the "3-WebApp-multi-APIs" project, try to target a multi-tenant app and authorize it using the "organizations" endpoint. You will get errors all over the place.

2. AuthorizeForScopesAttribute does really kick in unless you have the code in a try-catch block and some of it is just plain meaningless.
So when you have an attribute like this, you expect it to just work. Right? Some how it magically authorizes and you get a token in a Context object or something. Like how the AspNet/Core attribute AuthorizeAttribute works -- you just put [Authorize] on a controller or an action and the AspNet pipeline takes care of doing all the dirty work.

But with the AuthorizeForScopesAttribute, you have to still write the GetToken… code.

Now, here is the interesting & weird bit: the OnException function in the AuthorizeForScopesAttribute class does not trigger unless you have that GetToken… code in a try-catch block! Why??

All in all, I think this codebase has a lot of work to be done before it becomes ready as a production-worthy library. Until then, sure, it serves as a great sample, and lets you work with some individual scenarios.

[Feature Request] Allow multiple scopes from configuration for AuthorizeForScopesAttribute

Is your feature request related to a problem? Please describe.

AuthorizeForScopesAttribute does not support multiple scopes from configuration e.g. it's pretty common to want some custom app scope as well as Group.Member.Read

Describe the solution you'd like

Have a way to pull multiple scopes from configuration e.g. this could be done by checking if ScopeKeySection has children or introducing a new property called ScopesKeySection.

Describe alternatives you've considered

I've had to copy AuthorizeForScopesAttribute into my own code and make the change.

Additional context

Thanks for this library, it's awesome.

There should be an option to have TokenAcquisition be a singleton

This issue is for a: (mark with an x)

- [ ] bug report -> please search issues before submitting
- [ x] feature request
- [ ] documentation issue or request
- [ ] regression (a behavior that used to work and stopped in a new release)

Why?

Today, TokenAcquisition is a scoped by request. See https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/blob/ab84785cf757c2d3244090a90d563528ee4be616/Microsoft.Identity.Web/ServiceCollectionExtensions.cs#L38

There are scenarios, like using the Graph SDK, which require it to be a singleton. This is a request from the Graph SDK team (Darrel Miller).
Given Bogdan's analysis (below), this is safe to have a singleton.

What: proposed developer experience?

Provide an option in the configuration, which sets the TokenAcquisition service to be a singleton.

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
  
    // missing lines here ...

    "SingletonTokenAcquisition" :  false
  },

  // missing lines here ...
}

Proposed design:

  1. Add a boolean SingletonTokenAcquisition in the MicrosoftIdentityOptions, by default this would be false.
  2. Add a bool parameter in AddTokenAcquisition to specify if the token acquisition service should be a singleton or not (and use .AddScoped if it's not a singleton, and AddSignleton if this is a singleton)
  3. Pass this parameter in methods calling AddTokenAcquisition, the value coming from the MicrosoftIdentityOptions.SingletonTokenAcquisition. Probably:
    • AddProtectedWebApiCallsWebApis
    • AddWebAppCallsWebApis,

Issue copied from Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2#287, that will need to be updated

AddSignIn should be more robust to authority having or not a trailing slash.

WebApiAuthenticationBuilderExtensions.EnsureAuthorityIsV2_0 was extracted from the WebApiAuthenticationBuilderExtensions.AddProtectedWebAPi method so that we can unit test it. I think it should stay there as this method takes a JwtBearerOptions parameter and It's unit tested.

It provides a more robust processing of authorities accepting them to end in / or not.

We want to do somthing similar for WebAppAuthenticationBuilderExtensions.AddSignIn( this AuthenticationBuilder builder, Action<OpenIdConnectOptions> configureOpenIdConnectOptions, Action<MicrosoftIdentityOptions> configureMicrosoftIdentityOptions, string openIdConnectScheme = OpenIdConnectDefaults.AuthenticationScheme, string cookieScheme = CookieAuthenticationDefaults.AuthenticationScheme, bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents = false), but with a method enabling an OpenIdConnectOptions.

[Documentation] Ensure API reference documentation is published

Documentation Related To Component:

Ensure the NuGet package is picked-up by docs.ms and the reference documentation is generated

Please check those that apply

  • typo
  • [ x] documentation doesn't exist
  • documentation needs clarification
  • error(s) in example
  • needs example

Update README.md

TODO items
[ ] Fix links ex: Web applications as was copied over from the README attached to the sample
[ ] Update build status to reflect new CI build
[ ] Update the class diagrams
[ ] Reference the obsolete attributes ex: .AddMicrosoftIdentityPlatformAuthentication => AddSignIn
[ ] Chris Ross recommended we also add the services.AddAuthentication(AzureADDefaults.AuthenticationScheme) before. Something to think of
context:

public void ConfigureServices(IServiceCollection services)
  {
   ...
   services.AddSignIn(Configuration);

[ ] Other?
cc: @jmprieur @pmaytak

Identity.Web.UI should use Razor pages, not MVC

Why?

Microsoft.Identity.Web.UI (in removeUI branch) currently uses MVC. The advise of the ASP.NET Core team is to change it to use Razor pages because Razor pages have an extensibility model can be overridden by copy / paste in the user project, therefore replacing the pages which are provided by the library

What?
The advise of the ASP.NET Core team is to change MVC pages to Razor pages

Copied from Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2#290

[Investigate] Incorrect behavior using the issuer validator cache in AadIssuerValidator class

The authority in public static AadIssuerValidator GetIssuerValidator(string aadAuthority) is in the form of URI (ex. https://login.microsoftonline.com/).

In if (s_issuerValidators.TryGetValue(aadAuthority, out AadIssuerValidator aadIssuerValidator)) full authority string is used to query the issuer validator dictionary.

However, only the authority host is used as a key to insert the value.

string authority = authorityHost ?? new Uri(FallbackAuthority).Host;
...
s_issuerValidators[authority] = new AadIssuerValidator(aliases);

So the value is never retrieved in the cache, unless only the host is passed in while the cache has that key.
Investigate if this behavior is intended.

[Bug] Null reference exception calling AcquireTokenByAuthorizationCode when client secret is not specified (need to improve error message)

Which Version of MSAL are you using ?
4.5.1

Platform
.NET Core 3

What authentication flow has the issue?

  • Web App
    • Authorization code

Is this a new or existing app?
c. This is a new app or experiment

Repro
This is based on https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Acquiring-tokens-with-authorization-codes-on-web-apps but using WithB2CAuthority rather than WithAuthority.

IConfidentialClientApplication cca = ConfidentialClientApplicationBuilder
	.Create(AzureAdB2COptions.ClientId)
	.WithRedirectUri(AzureAdB2COptions.RedirectUri)
	.WithB2CAuthority(AzureAdB2COptions.Authority)
	.Build();

var builder = cca.AcquireTokenByAuthorizationCode(new[] { "openid" }, context.ProtocolMessage.Code);
AuthenticationResult result = await builder.ExecuteAsync();

Expected behavior
I was expecting to retrieve an access token in line with https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-reference-oauth-code#2-get-a-token

Actual behavior
Exception is thrown by ExecuteAsync(). Stack-trace as follows (awaits removed):

at Microsoft.Identity.Client.Internal.ClientCredentialWrapper.get_Thumbprint()
at Microsoft.Identity.Client.Internal.JsonWebToken.JWTHeaderWithCertificate..ctor(ClientCredentialWrapper credential, Boolean sendCertificate)
at Microsoft.Identity.Client.Internal.JsonWebToken.EncodeHeaderToJson(ClientCredentialWrapper credential, Boolean sendCertificate)
at Microsoft.Identity.Client.Internal.JsonWebToken.Encode(ClientCredentialWrapper credential, Boolean sendCertificate)
at Microsoft.Identity.Client.Internal.JsonWebToken.Sign(ClientCredentialWrapper credential, Boolean sendCertificate)
at Microsoft.Identity.Client.Internal.Requests.ClientCredentialHelper.CreateClientCredentialBodyParameters(ICoreLogger logger, ICryptographyManager cryptographyManager, ClientCredentialWrapper clientCredential, String clientId, AuthorityEndpoints endpoints, Boolean sendX5C)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.<SendTokenRequestAsync>d__21.MoveNext()
at Microsoft.Identity.Client.Internal.Requests.AuthorizationCodeRequest.<ExecuteAsync>d__3.MoveNext()
at Microsoft.Identity.Client.Internal.Requests.RequestBase.<RunAsync>d__14.MoveNext()
at Microsoft.Identity.Client.ApiConfig.Executors.ConfidentialClientExecutor.<ExecuteAsync>d__2.MoveNext()

Possible Solution
I had a look at the master (512d74e) and at RequestBase.cs line 300 there is a condition if (AuthenticationRequestParameters.ClientCredential != null) which must be succeeding to get that stack trace. I would have expected this to be null as I'm executing AcquireTokenByAuthorizationCode and not a client credentials grant.

The WebApp-OpenIDConnect-DotNet sample includes .WithClientSecret(AzureAdB2COptions.ClientSecret) and using this makes the exception go away, but doesn't resolve the problem because it generates an error in B2C: "'AADB2C90079: Clients must send a client_secret when redeeming a confidential grant".

Port code from ASP.NET Core Web app sample and have two dev samples

What?

  1. Port the code of Microsoft.Identity.Web, Microsoft.Identity.Web.UI and Microsoft.Identity.Web.Tests to this repo under the src folder

  2. under dev-samples:

    1. Add the Web app calls Web API sample, and change it so that the Web API also calls Microsoft Graph (so that we experience the full end to end)
    2. Add the B2C Web app calls Web API sample

[Bug] Custom TokenValidationParameters.ValidAudiences is overwritten

Which Version of Microsoft Identity Web are you using ?
preview

Where is the issue?

  • Web App
    • Sign-in users
    • Sign-in users and call web APIs
  • Web API
    • Protected web APIs (Validating tokens)
    • Protected web APIs (Validating scopes)
    • Protected web APIs call downstream web APIs
  • Token cache serialization
    • In Memory caches
    • Session caches
    • Distributed caches

Other? - please describe;

Repro
As a developer, I might want to have my valid audience to be https://<tenantDomain> instead of api://<guid>.

For that I could use:

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddProtectedWebApi("AzureAd", Configuration, options =>
                {
                    Configuration.Bind("AzureAD", options);
                    options.TokenValidationParameters.ValidAudiences = new List<string> { "https://<myTenantDomain>" };
                });

Expected behavior
Have the options.TokenValidationParameters.ValidAudiences set with my custom option.

Actual behavior
The method EnsureValidAudiencesContainsApiGuidIfGuidProvided() is overwriting my audiences in its logic.

Possible Solution
Have EnsureValidAudiencesContainsApiGuidIfGuidProvided() to extend my options and not overwrite it.

Additional context/ Logs / Screenshots
Add any other context about the problem here, such as logs and screenshots.

Needs help on Securing a web app

Hi ,

This is not bug , but needs a help on how to do this feature.
I have a web app (Flask ) A created by following this tutorial. Link
And I have another website B hosted in another host provider and trying to access above api from B.
I added CORS in A but want to impliment an oAuth2 in azure . how to do that?
I am looking a scenario where credentials prompt is not shown . like a deamon app it should be able to get the token.
I am new to all these. Hope you got what am i looking into.

Get AccessTokenOnBehalfOfUser if (Current)HttpContext is not available (anymore)

From @pocki and copied from Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2#233

This issue is for a: (mark with an x)

- [ ] bug report -> please search issues before submitting
- [ ] feature request
- [x] documentation issue or request
- [ ] regression (a behavior that used to work and stopped in a new release)

The issue was found for the following scenario:

Please add an 'x' for the scenario(s) where you found an issue

  1. Web app that signs in users
    1. with a work and school account in your organization: 1-WebApp-OIDC/1-1-MyOrg
    2. with any work and school account: /1-WebApp-OIDC/1-2-AnyOrg
    3. with any work or school account or Microsoft personal account: 1-WebApp-OIDC/1-3-AnyOrgOrPersonal
    4. with users in National or sovereign clouds 1-WebApp-OIDC/1-4-Sovereign
    5. with B2C users 1-WebApp-OIDC/1-5-B2C
  2. Web app that calls Microsoft Graph
    1. Calling graph with the Microsoft Graph SDK: 2-WebApp-graph-user/2-1-Call-MSGraph
    2. With specific token caches: 2-WebApp-graph-user/2-2-TokenCache
    3. Calling Microsoft Graph in national clouds: 2-WebApp-graph-user/2-4-Sovereign-Call-MSGraph
  3. Web app calling several APIs 3-WebApp-multi-APIs
  4. Web app calling your own Web API 4-WebApp-your-API
  5. Web app restricting users
    1. by Roles: 5-WebApp-AuthZ/5-1-Roles
    2. by Groups: 5-WebApp-AuthZ/5-2-Groups
  6. Deployment to Azure
  7. Other (please describe)

Repro-ing the issue

Repro steps

Is it somehow possible to receive an AccessToken on behalf of User if only (at least) ClaimsPrincipal (like in #159) is available but no full (Current)HttpContext?
Why: I have a long running task moved to a IHostedService. In this service I need an AccessToken at beginning and at the end (for the same scope). The AccessToken for the beginning is no problem, I can request it before the start and/or use the TokenCache. But in the end (>1 hour after begin) of the HostedService the token needs to be refreshed, but I can not call the TokenAcquisition because HttpContext is not available (out of Scope/Disposed) in IHostedService.

Actually I use TokenAcquisition.GetAccessTokenOnBehalfOfUserAsync to get and to "refresh"/get a new token

Expected behavior

Use of TokenAcquisition.GetAccessTokenOnBehalfOfUserAsync where HttpContext is not available (Disposed or out of Scope)

Actual behavior

With modifications of #159 I can pass the HttpContext.User as a Parameter to the HostedService: System.NullReferenceException "Object reference not set to an instance of an object."

var request = CurrentHttpContext.Request; //CurrentHttpContext is null/is already disposed
at Microsoft.Identity.Web.TokenAcquisition.BuildConfidentialClientApplication() in C:\xxx\Microsoft.Identity.Web\TokenAcquisition.cs:line 345
at Microsoft.Identity.Web.TokenAcquisition.GetOrBuildConfidentialClientApplication() in C:\xxx\Microsoft.Identity.Web\TokenAcquisition.cs:line 333

Line numbers may not match with this Repo

Possible Solution

Is it possible to set needed values for TokenAquisition manually?
Is there another method instead of TokenAcquisition.GetAccessTokenOnBehalfOfUserAsync to refresh a token?

Versions

ASP.NET Core 3.0
Microsoft.Identity.Web from this Repo, manually updated to ASP.NET Core 3.0 with

    <PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="3.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.AzureADB2C.UI" Version="3.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.1" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.1" />
    <PackageReference Include="Microsoft.Identity.Client" Version="4.7.1" />

Mention any other details that might be useful

Is there any other possiblity? Have I missed something? Anyone another suggestion how to solve this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.