I've set up my web app using OpenIDConnectAuthentication as follows. The OnAuthorizationCodeReceived notification uses Microsoft.IdentityModel.Clients.ActiveDirectory 3.13.8.
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
MetadataAddress = Settings.AADB2CAuth.SignInPolicyMetaAddress, // https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration?p={policy} policy = B2C_1_SignIn
AuthenticationType = Settings.AADB2CAuth.SignInPolicyId, // B2C_1_SignIn
ClientId = Settings.AADB2CAuth.ClientId, // {guid}
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = OnAuthenticationFailed,
AuthorizationCodeReceived = OnAuthorizationCodeReceived
},
RedirectUri = Settings.AADB2CAuth.RedirectUri,
Scope = "openid",
ResponseType = "id_token",
});
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
{
var code = context.Code;
ClientCredential clientCredential = new ClientCredential(Settings.AADB2CAuth.ClientId, Settings.AADB2CAuth.ClientSecret);
string userObjectID = context.AuthenticationTicket.Identity.FindFirst(Settings.ClaimTypes.ObjectIdentifier).Value;
string authority = Settings.AADB2CAuth.Authority; // https://login.microsoftonline.com/{tenant}
AuthenticationContext authContext = new AuthenticationContext(authority, new ADAL.ADALTokenCache(userObjectID));
Uri redirectUri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path));
AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(code, redirectUri, clientCredential, Settings.AADGraphApi.GraphResourceId);
}
This works fine. However an authorization code is not returned with the id_token. If change this to code id_token or just code, the AuthorizationCodeReceived notification fires, but then I am met with the error
AADSTS70000: Authentication failed: Authorization Code is malformed or invalid
Basically what I'm trying to do is access the B2C AD as the current signed in user. Is this at all possible?
I updated my Authentication Options to
new OpenIdConnectAuthenticationOptions
{
AuthenticationType = Settings.AADB2CAuth.SignInPolicyId,
Authority = string.Format("https://login.microsoftonline.com/tfp/{0}/{1}", Settings.AADB2CAuth.Tenant, Settings.AADB2CAuth.SignInPolicyId),
ClientId = Settings.AADB2CAuth.ClientId,
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = OnAuthenticationFailed,
AuthorizationCodeReceived = OnAuthorizationCodeReceived
},
RedirectUri = Settings.AADB2CAuth.RedirectUri,
Scope = "openid",
ResponseType = "code id_token",
});
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
{
var code = context.Code;
ClientCredential clientCredential = new ClientCredential(Settings.AADB2CAuth.ClientId, Settings.AADB2CAuth.ClientSecret);
string userObjectID = context.AuthenticationTicket.Identity.FindFirst(Settings.ClaimTypes.ObjectIdentifier).Value;
string authority = string.Format("https://login.microsoftonline.com/tfp/{0}/{1}", Settings.AADB2CAuth.Tenant, Settings.AADB2CAuth.SignInPolicyId);
AuthenticationContext authContext = new AuthenticationContext(authority, new ADAL.ADALTokenCache(userObjectID));
Uri redirectUri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path));
AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(code, redirectUri, clientCredential, Settings.AADGraphApi.GraphResourceId);
}
I am now met with an exception whose details are the HTML content of a 404 page. Looking at the requests I believe it is because AcquireTokenByAuthorizationCodeAsync is looking at https://login.microsoftonline.com/tfp/oauth2/token to send the authorization code to, which I don't think it should?
It may be worth noting that the Authorization Code header I get back is the following:
{
"kid": "cpimcore_09252015",
"ver": "1.0"
}
A quick google search for this yields one result and this references the following issue on the Android ADAL. I'm not sure if this relates to my issue however.
If you look at the beginning of this error:
AADSTSXXXXX
means that when you tried to exchange your auth code, you went to the AAD sts rather than the expected B2C sts:
AADB2CXXXXX
This means your auth code post request was interpreted incorrectly by our endpoint. This is usually caused when the policy (p=B2C_1_xxxx) param for B2C gets appended onto the post URL rather than inside the request.
Option 1:
Refactor your code and library usage to stick the policy param inside the auth code post request rather than the end of the token endpoint URL.
Option 2:
Use the alternate token endpoint and don't tack on any poliy param. Your new endpoint would look like this
https://login.microsoftonline.com/tfp/{tenant}/B2C_1_myB2CPolicy/oauth2/v2.0/token
Related
I have this Startup.cs which is taken basically from the MS project template. That should be Authorization Code Flow to authenticate with Azure Active Directory. But it throws an execption with the following message, which says it tries to be a implicit auth flow. But why? How can i force Auth Code Flow? Is there a working example?
I use ASP.NET MVC (NOT Core), 4.xxxx something. The most recent. And Owin.
I get this error: https://login.microsoftonline.com/error?code=700054 and it when i debug, it does not execute "AuthorizationCodeReceived".
Current code:
public void Configuration(IAppBuilder app)
{
string clientId = WebConfigurationManager.AppSettings["ClientId"];
string authority = "https://login.microsoftonline.com/" + WebConfigurationManager.AppSettings["Tenant"] + "/v2.0";
string appKey = WebConfigurationManager.AppSettings["ClientSecret"];
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 = WebConfigurationManager.AppSettings["RedirectUri"],
// PostLogoutRedirectUri is the page that users will be redirected to after sign-out. In this case, it is using the home page
PostLogoutRedirectUri = WebConfigurationManager.AppSettings["RedirectUri"],
//Scope = OpenIdConnectScope.OpenIdProfile,
// ResponseType is set to request the id_token - which contains basic information about the signed-in user
//ResponseType = OpenIdConnectResponseType.IdToken,
// ValidateIssuer set to false to allow personal and work accounts from any organization to sign in to your application
// To only allow users from a single organizations, set ValidateIssuer to true and 'tenant' setting in web.config to the tenant name
// To allow users from only a list of specific organizations, set ValidateIssuer to true and use ValidIssuers parameter
TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = false // Simplification (see note below)
},
// OpenIdConnectAuthenticationNotifications configures OWIN to send notification of failed authentications to OnAuthenticationFailed method
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = OnAuthenticationFailed,
// If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
AuthorizationCodeReceived = (context) =>
{
var code = context.Code;
ClientCredential credential = new ClientCredential(clientId, appKey);
string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
AuthenticationContext authContext = new AuthenticationContext(authority, null);
AuthenticationResult result = authContext.AcquireTokenByAuthorizationCodeAsync(
code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId).Result;
return Task.FromResult(0);
}
}
}
);
}
private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> arg)
{
throw new NotImplementedException();
}`enter code here`
Here Angularjs is front end and Web API is middle tier. we are using AzureAD OpenID connect for Authentication.
I'm facing following issue. because of the my landing page is not loading
Access to XMLHttpRequest at 'https://login.microsoftonline.com/xx-86f1-41af-91ab-xxx/oauth2/authorize?client_id=xxxx1&response_mode=form_post&response_type=code%20id_token&scope=openid%20profile&state=OpenIdConnect.AuthenticationPropertiesxxxxx&noncexxxxx&redirect_uri=https%3A%2F%2Flocalhost%3A44300%2F&x-client-SKU=ID_NET451&x-client-ver=5.2.1.0' (redirected from 'https%3A%2F%2Flocalhost%3A44300%2F/api/Scorecard/GetServiceNameWithManagers?loginUser=xxx#microsoft.com') from origin 'https%3A%2F%2Flocalhost%3A44300%2F' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I've done lot of research and applied Access-Control-Allow-Origin =* at Request and response. also applied app.UseCors(Owin.Cors.CorsOptions.AllowAll);
but so far no success.
consider following code, AuthorizationCodeReceived delegate is not invoking very first time even though the user is logged in to microsoft site.
Please be noted, this code is not working very first time. It will work after few button clicks (postbacks) and then after few minutes if we run the application it's throws CORS preflight issue. Please help.
This is my startup.cs
public void Configuration(IAppBuilder app)
{
app.UseCors(Owin.Cors.CorsOptions.AllowAll);
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies",
CookieManager = new SystemWebChunkingCookieManager(),
});
//// Bearer token authentication middleware.(Ex: request from web clients,ajax calls able to pass authenticated bearer info)
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"],
TokenReplayCache = new TokenReplayCache(new MemoryCacheProvider())
},
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
Provider = new OAuthBearerAuthenticationProvider
{
OnValidateIdentity = ctx =>
{
//// Retrieve user roles from the request.
var authenticationTicket = ctx.Ticket;
if (authenticationTicket.Identity.IsAuthenticated)
{
////Use the block when role/user specific authorization needs and to modify the user identity claims based on requirement
}
return Task.FromResult(0);
},
OnRequestToken = ctx => { return Task.FromResult(0); }
}
});
//// Non Bearer authentication middleware. (Ex: request secured web api call directly from URL/Web API server scope it self)
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = ClientId,
ClientSecret = ConfigurationManager.AppSettings["ida:AppKey"],
Authority = Authority,
PostLogoutRedirectUri = PostLogoutRedirectUri,
AuthenticationMode = AuthenticationMode.Active,
ResponseType = "code id_token",
CallbackPath = new PathString("/"),
Notifications = new OpenIdConnectAuthenticationNotifications()
{
SecurityTokenValidated = context =>
{
if (context.AuthenticationTicket.Identity.IsAuthenticated)
{
////Use the block when role/user specific authorization needs and to modify the user identity claims based on requirement
}
return Task.FromResult(0);
},
AuthorizationCodeReceived = async context =>
{
var code = context.Code;
ClientCredential credential = new ClientCredential(ClientId, Models.ConfigurationData.GraphSecret);
string userObjectID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
AuthenticationContext authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectID));
Uri uri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path));
AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(code, uri, credential, GraphResource);
},
RedirectToIdentityProvider = context =>
{
if (context.ProtocolMessage.RedirectUri == null)
{
////To set the reply/redirect Url based on the request host environment.
////Hosting env details we get only through the owin context in startup and this is the delegate to set reply URL in OWincontext before the authentication.
string ReplyAddress = context.Request.Scheme + "://" + context.Request.Host + "/";
context.ProtocolMessage.RedirectUri = ReplyAddress;
}
//context.OwinContext.Authentication.User.Identity.IsAuthenticated = true;
if (context.OwinContext.Authentication.User.Identity.IsAuthenticated && context.ProtocolMessage.RequestType != IdentityModel.Protocols.OpenIdConnect.OpenIdConnectRequestType.Logout)
{
////To avoid infinite loop of redirections in request if user is authenticated and unauthorized.
context.HandleResponse();
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
}
return Task.FromResult(0);
}
},
TokenValidationParameters = new TokenValidationParameters
{
RoleClaimType = "roles",
TokenReplayCache = new TokenReplayCache(new MemoryCacheProvider())
},
});
System.Web.Helpers.AntiForgeryConfig.UniqueClaimTypeIdentifier = System.IdentityModel.Claims.ClaimTypes.NameIdentifier;
}
Access to XMLHttpRequest at 'https://login.microsoftonline.com/xx-86f1-41af-91ab-xxx/oauth2/authorize?client_id=xxxx1&response_mode=form_post&response_type=code%20id_token&scope=openid%20profile&state=OpenIdConnect.AuthenticationPropertiesxxxxx&noncexxxxx&redirect_uri=https%3A%2F%2Flocalhost%3A44300%2F&x-client-SKU=ID_NET451&x-client-ver=5.2.1.0' (redirected from 'https%3A%2F%2Flocalhost%3A44300%2F/api/Scorecard/GetServiceNamxxxManagers?loginUser=xxx#microsoft.com') from origin 'https%3A%2F%2Flocalhost%3A44300%2F' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I think you misunderstood the error message. It says that your AngularJS application was trying to make a request to https://login.microsoftonline.com/xxx-xx-41af-91ab-xxx/oauth2/authorize and failed, because it was a cross-origin request and the server didn't approve it by returning the Access-Control-Allow-Origin header in a response to preflight request (HTTP method OPTIONS).
So you cannot change it by adding CORS headers to your backend. The authorize is not designed to be called by XMLHttpRequest requests - you are supposed to make a full browser request to that URL. Later, the browser will be redirected to redirect_uri (the request parameter value) along with an auth code or an error.
We're using IdentityServer4 for our IdentityServer and IdentityServer3 for the client (ASP.NET MVC 5).
Everything works (the User/Claimsprincipal is set correctly through OWIN) except I cannot get the access token from the User.
We're using a implicit client which has access to these scopes: openid, profile, testapi
Startup.cs:
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = identityServerUrl,
RequiredScopes = new[] { "testapi" },
});
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies",
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
Authority = identityServerUrl,
ClientId = "testclient",
Scope = "openid profile testapi",
RedirectUri = "http://localhost:49000/signin-oidc",
ResponseType = "id_token token",
SignInAsAuthenticationType = "Cookies",
});
Code to retrieve Access Token (inside one of the controllers):
var user = User as ClaimsPrincipal;
var token = user.FindFirst("access_token");
User is set correctly, but the token is null. I am guessing it is some kind of option that I am missing in the startup.cs, but which?
I think a simpler solution is to use what is allready made availible:
var options = new IdentityServerBearerTokenAuthenticationOptions
{
Authority = authorityUrl,
PreserveAccessToken = true,
};
Then the access token is availible as a claim (named 'token') on the User principle.
I found a solution that does exactly what I want - I'm putting it here for anyone else running into the problem. It costs a dependency on IdentityModel, but that is acceptable in my case:
In Startup.cs, I added:
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = async n =>
{
var tokenClient = new TokenClient(identityServerUrl + "/connect/token", clientId, secret);
var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, n.RedirectUri);
HttpContext.Current.Session[HttpUserContext.ACCESS_TOKEN] = tokenResponse.AccessToken;
}
}
To the call to .UseOpenIdConnectAuthentication
I hope anyone is able to help me out with this problem
Im trying to get one of the code samples from the Microsoft Graph Api working with a company specific application. After I sign in at my tenant's sign in screen im getting redirected to the application with the following error.
AADSTS90130: Application '{application id}'
(aad name) is not supported over the /common or /consumers
endpoints. Please use the /organizations or tenant-specific endpoint.
In my startup class i've got the following code:
// The graphScopes are the Microsoft Graph permission scopes that are used by this sample: User.Read Mail.Send
private static string appId = ConfigurationManager.AppSettings["ida:AppId"];
private static string appSecret = ConfigurationManager.AppSettings["ida:AppSecret"];
private static string redirectUri = ConfigurationManager.AppSettings["ida:RedirectUri"];
private static string graphScopes = ConfigurationManager.AppSettings["ida:GraphScopes"];
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
// The `Authority` represents the Microsoft v2.0 authentication and authorization service.
// The `Scope` describes the permissions that your app will need. See https://azure.microsoft.com/documentation/articles/active-directory-v2-scopes/
ClientId = appId,
Authority = "https://login.microsoftonline.com/{tenantid}",
PostLogoutRedirectUri = redirectUri,
RedirectUri = redirectUri,
Scope = "openid email profile offline_access " + graphScopes,
TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
// In a real application you would use IssuerValidator for additional checks,
// like making sure the user's organization has signed up for your app.
// IssuerValidator = (issuer, token, tvp) =>
// {
// if (MyCustomTenantValidation(issuer))
// return issuer;
// else
// throw new SecurityTokenInvalidIssuerException("Invalid issuer");
// },
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = async (context) =>
{
var code = context.Code;
string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
TokenCache userTokenCache = new SessionTokenCache(signedInUserID,
context.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase).GetMsalCacheInstance();
ConfidentialClientApplication cca = new ConfidentialClientApplication(
appId,
redirectUri,
new ClientCredential(appSecret),
userTokenCache,
null);
string[] scopes = graphScopes.Split(new char[] { ' ' });
AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(code, scopes);
},
AuthenticationFailed = (context) =>
{
context.HandleResponse();
context.Response.Redirect("/Error?message=" + context.Exception.Message);
return Task.FromResult(0);
}
}
});
}
}
In this code I have the tenant-specific id in the sign in url which works for another application with the same sign-in style.
I'm not sure what is wrong so i'm hoping there is someone who can help me out. I've looked at related questions on here but none seem related to this issue.
You're using the v1 Endpoint to register your application via the Azure Portal and set Multi-tenant to false. This will restrict your application to only AAD users from the tenant at which it's registered.
If you want to accept any AAD user, you'll need to enable multiple tenants. This will allow a report AAD tenant to recognize your application and allow users to authenticate.
If you want to accept both AAD and MSA users, you'll need to register your application at https://apps.dev.microsoft.com. You'll also need to refactor your authentication code to use the v2 Endpoint.
I am trying to use ADFS Authentication with OAuth to communicate between my webapp and webapi. I am using ADFS4 and have configured application group with Server application and Webapi accordingly. I am trying to receive the userdetails, particularly the username from the webapi controller. Is it possible to pass the username details within the access token passed to webapi. Here is what I did from the Webapp side:
In the webapp controller after adfs authentication,
authContext = new AuthenticationContext(Startup.authority, false);
ClientCredential credential = new ClientCredential(Startup.clientId, Startup.appKey);
string accessToken = null;
bool isAuthenticated = User.Identity.IsAuthenticated; //return true
string username = User.Identity.Name; // returns username
string userId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Name).Value; // returns username
HttpClient httpClient = new HttpClient();
try
{
result = authContext.AcquireTokenAsync(Startup.apiResourceId, credential).Result;
accessToken = result.AccessToken;
}
catch (AdalException ex)
{
}
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
HttpResponseMessage response = httpClient.GetAsync(Startup.apiResourceId + "/api/ConfApi").Result;
From the Webapi end, in Startup.Auth.cs, I have added these code
public void ConfigureAuth(IAppBuilder app)
{
JwtSecurityTokenHandler.InboundClaimTypeMap.Clear();
app.UseActiveDirectoryFederationServicesBearerAuthentication(
new ActiveDirectoryFederationServicesBearerAuthenticationOptions
{
MetadataEndpoint = ConfigurationManager.AppSettings["ida:AdfsMetadataEndpoint"],
TokenValidationParameters = new TokenValidationParameters() {
SaveSigninToken = true,
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"]
}
});
}
However, within the ConfApi controller, I cannot find any claims with user details.
What can I do to receive user details in the Webapi controller?
Thanks for any help.
Are you actually receiving the claims?
Did you configure claims rules for the web API on the ADFS side?
What did you use for Name - Given-Name, Display-Name etc?
Use something like Fiddler to monitor the traffic. After the OIDC authentication, you should see access tokens, id tokens etc.
Take the token and copy into jwt.io.
This will show you what you are actually receiving.
However, the OWIN classes translate the simple OAuth attributes e.g. "aud" into the claim type URI e.g. http://claims/this-claim so breakpoint and see what is in the claims collection and what type has been assigned to each.
The answer to this is the same answer to the question: MSIS9649: Received invalid OAuth request. The 'assertion' parameter value is not a valid access token
You have to use authorization code flow (instead of client credentials grant flow) to get the server app (web app in this case) to talk to the web API with the user's context. Authorization code flow will pass the claims in the JWT Token. Just make sure you pass thru any claims you need for the web API in the web API's RPT claim issuance transform rules.
Vittorio has a nice post on authorization code flow, although it talks about azure.
In order to use authorization code flow, you need to handle the AuthorizationCodeReceived Event via Notifications on the OpenIdConnectAuthenticationOptions from Startup.ConfigureAuth(IAppBuilder app)
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions {
...
Notifications = new OpenIdConnectAuthenticationNotifications {
AuthorizationCodeReceived = async code => {
ClientCredential credential = new ClientCredential(Startup.clientId, Startup.appKey);
AuthenticationContext authContext = new AuthenticationContext(Startup.authority, false);
AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(
code.Code,
new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)),
credential,
Startup.apiResourceId);
}
}
When you are ready to make the call you acquire your token silently.
var authContext = new AuthenticationContext(Startup.authority, false);
var credential = new ClientCredential(Startup.clientId, Startup.appKey);
var claim = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
var userId = new UserIdentifier(claim, UserIdentifierType.UniqueId);
result = await authContext.AcquireTokenSilentAsync(
Startup.apiResourceId,
credential,
userId);
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Bearer",
result.AccessToken);