Token request failed at TokenHelper.GetAccessToken() when using OAuth2S2SClient - sharepoint-online

I created a SharePoint provider hosted app and it was working fine when I published and added to the site. I created a CName and registered in using appregnew page, deployed the cloud service project, installed and added the app. I am getting the same error on the page I have authentication [SharePointContextFilter]. the page without authentication [SharePointContextFilter] is working fine.
Below is the detailed error:
Error occured. Token request failed. Inner:System.Net.WebException: The remote server returned an error: (400) Bad Request. at System.Net.HttpWebRequest.GetResponse() at Microsoft.IdentityModel.S2S.Protocols.OAuth2.OAuth2WebRequest.GetResponse() at Microsoft.IdentityModel.S2S.Protocols.OAuth2.OAuth2S2SClient.Issue(String securityTokenServiceUrl, OAuth2AccessTokenRequest oauth2Request) Stacktace: at Microsoft.IdentityModel.S2S.Protocols.OAuth2.OAuth2S2SClient.Issue(String securityTokenServiceUrl, OAuth2AccessTokenRequest oauth2Request) at PasswordResetAppWeb.TokenHelper.GetAccessToken(String refreshToken, String targetPrincipalName, String targetHost, String targetRealm) at PasswordResetAppWeb.SharePointAcsContext.RenewAccessTokenIfNeeded(Tuple2& accessToken, Func1 tokenRenewalHandler) at PasswordResetAppWeb.SharePointAcsContext.GetAccessTokenString(Tuple2& accessToken, Func1 tokenRenewalHandler) at PasswordResetAppWeb.Controllers.PasswordProfilesController.Index() Stacktace:Microsoft.IdentityModel.Extensions
Any idea what I am doing wrong?
I used the Cname URL for both registering the app using appregnew.aspx and I also used the Cname URL when I packaged the app. What am I doing wrong here?
Any suggestions would be great.. Thanks in advance!!

I got it. I didn't copy the client secret id properly to the web.config. It had a space in it and that caused the issue.
So steps are correct to add alias names to sharepoint apps hosted in cloud service:
register app with new CName, change the clientID, Client Secret in webconfig and deploy, package the app using Cname and clientID and install and add the app.
Make sure your client ID and client secret is copied correctly.
Edit 7/31/2022: I got the exact same error again and this time I fixed it by enabling TLS 1.2.
// Get token
OAuth2S2SClient client = new OAuth2S2SClient();
OAuth2AccessTokenResponse oauth2Response;
const SslProtocols _Tls12 = (SslProtocols)0x00000C00;
const SecurityProtocolType Tls12 = (SecurityProtocolType)_Tls12;
ServicePointManager.SecurityProtocol = Tls12;
try
{
oauth2Response =
client.Issue(AcsMetadataParser.GetStsUrl(targetRealm), oauth2Request) as OAuth2AccessTokenResponse;
}

Related

msal-node error trying to resolve endpoints

I have been using MSAL in my React app for some time with success. One of the tokens that my app requests is for scope 'https://management.core.windows.net/user_impersonation'. I have a nodeJS server that I want to push that token acquisition to so I installed msal-node (1.12.1) and tried using the OBO flow:
const pca = new msal.ConfidentialClientApplication({
auth: {
clientId: settings.config.azure.clientId,
clientSecret: settings.config.azure.clientSecret,
authority: "https://login.microsoftonline.com/<tenantid>",
knownAuthorities: ["https://login.microsoftonline.com/<tenantid>"],
}
});
const request = {
scopes: ['https://management.core.windows.net//user_impersonation'],
oboAssertion: <token_extracted_from_auth_header>
}
const response = await pca.acquireTokenOnBehalfOf(request);
return response.accessToken;
However the above code results in the following error:
ClientAuthError: endpoints_resolution_error: Error: could not resolve endpoints. Please check network and try again. Detail: ClientAuthError: openid_config_error: Could not retrieve endpoints. Check your authority and verify the .well-known/openid-configuration endpoint returns the required endpoints. Attempted to retrieve endpoints from: https://login.microsoftonline.com/tenantid/v2.0/.well-known/openid-configuration
If I visit the URL it complains about I do get back some metadata so not really sure why it is failing.
Anybody have a suggestion?
Also in regards to OBO flow:
For my nodeJS app I have added that permission to the required API list
I presume the oboAssertion field is the token that is passed to my nodeJS app by the client? I simply extracted it from the Auth header
The actual error message there means that the URL that we are trying to contact is wrong. And it is wrong https://login.microsoftonline.com/tenantid/v2.0/.well-known/openid-configuration returns an error.
A coorrect one is: https://login.microsoftonline.com/19d5f71f-6c9a-4e7f-b629-2b0c38f2b167/v2.0/.well-known/openid-configuration
Notice how I used an actual teanant_id there. You can get yours from the Azure Portal - it's the "directory id"
If your web api is single tenant, i.e. it is only meant for the people in 1 organization, then the is the tenant id of that organization. It is also known as "directory id". You get it from the Azure Portal.
However, if your api is multi-tenant, i.e. it's a bit more complicated, and the "correct" answer is to use the tenant id of the incoming assertion. It's the tid claim in it.

Resource Token Provider as an Azure Function

I've been following the guide in this repo to setup a resource token provider as an Azure function.
https://github.com/adamhockemeyer/Azure-Functions---CosmosDB-ResourceToken-Broker
I've setup the Cosmos DB, App registration, and Azure function with permissions according to the instructions. When I get to step 3 in the guide where I enter https://{function-url}/.auth/login/{provider} into my browser I get the following error.
ADSTS50011: The reply url specified in the request does not match the
reply urls configured for the application: [App id]
Update
I changed the Reply URL in my App Registration to https://{function-url}/.auth/login/{provider}/callback with {function-url} as my Function App URL. Originally I had it set to one of my Function URL's. Now i'm getting a 404 not found error.
App Registration Redirect URL
Function App URL
Function App Authentication Settings
You need to add the URL as below in your app registration, then it should work.
Note: After adding the URl, go back to the Authentication / Authorization in your functionapp, turn off the Authentication Providers whcih you configured -> turn off Authentication / Authorization, then turn on and configure again, otherwise it seems not become effective.
https://{function-url}/.auth/login/{provider}/callback
Update:
Turn off all the configuration and create the new AD App like below.

Azure MSI using app services

I am trying to protect my backing services to my frontend webapp using MSI and AAD auth.
I keep getting a 401 when I call my backing services form the public facing webapp. I have added the public webapp as a reader in the IAM section of the backing services.
What I can't figure out is how to obtain the access token, it seems that no matter which endpoint I use for obtaining the access token, it says that it is not found.
Here is my code:
{
var azureServiceTokenProvider = new AzureServiceTokenProvider();
string accessToken = azureServiceTokenProvider.GetAccessTokenAsync("https://<mywebapi>.azurewebsites.net").GetAwaiter().GetResult();
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new
AuthenticationHeaderValue("Bearer", accessToken);
RemoteIp = httpClient.GetStringAsync("https://<mywebapi>.azurewebsites.net/api/default/remoteIp").GetAwaiter().GetResult();
LocalIp = httpClient.GetStringAsync("https://<mywebapi>.azurewebsites.net/api/default/localIp").GetAwaiter().GetResult();
ConnectionId = httpClient.GetStringAsync("https://<mywebapi>.azurewebsites.net/api/default/connectionId").GetAwaiter().GetResult();
}
And here is the error message:
Parameters: Connectionstring: [No connection string specified], Resource: https://<mywebapi>.azurewebsites.net, Authority: .
Exception Message: Tried to get token using Managed Service Identity.
Unable to connect to the Managed Service Identity (MSI) endpoint.
Please check that you are running on an Azure resource that has MSI setup.
UPDATE:
<mywebapi> is obviously the actual endpoint value, but not exposed here on stackoverflow. Furthermore I should mention that calling the API endpoints directly works fine, after I have authorized with my personal credentials xxx#xxx.xxx. The issue is related to the webapp trying to identify itself to the webapi, even though it is a registered application which has been assigned the necessary IAM rights on the webapi resource.
The error says it tried to use MSI, but could not. Are you sure you are running this code on the Web App with MSI enabled?
Also, you need to replace "https://<mywebapi>.azurewebsites.net" with the App Id URI or Application Id of your API in Azure AD.
In other words, this needs to match the valid audience that you have configured for the API.

IDX10803 and IDX10804 error with Azure AD

I have created a Web API in ASP.NET Core 2 and it is secured with Azure AD. The requests work fine in my dev environment. However when I publish the API to IIS and pass in a Authorization header in request I am getting these error:
fail: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[3]
Exception occurred while processing message.
System.InvalidOperationException: IDX10803: Unable to obtain configuration from: 'https://login.microsoftonline.com/xxxx/.well-known/openid-configuration'. ---> System.IO.IOException: IDX10804: Unable to retrieve document from: 'https://login.microsoftonline.com/xxxx/.well-known/openid-configuration'. ---> System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.Http.WinHttpException: A connection with the server could not be established
What am I doing wrong? I can browse the url in browser successfully.
I figured it out. It was because of a proxy setting to access the internet. Since ASP.NET Core does not pick up proxy setting from system.net area of web.config, the ideal solution was to create a middle ware to act as proxy.
I was running short of time. So I created a new user and logged on server with that new user and configured the proxy settings in Internet Explorer options. Then I configured the App Pool in IIS to run under that user's identity. Problem solved!
The correct answer is to add a proxy to the metadata request that ADAL makes using BackchannelHttpHandler. You can do it like this:
public void Configure(string name, JwtBearerOptions options)
{
options.BackchannelHttpHandler = new HttpClientHandler
{
UseProxy = true,
Proxy = new WebProxy
{
Address = new Uri($"{appSettings.InternetProxyUrl}:{appSettings.InternetProxyPort}"),
UseDefaultCredentials = true
}
};
}

ASP.NET Core Web App using Work (Azure AD) Authentication works debugging locally, but not after publish to Azure

My ASP.NET Core web app works great when running and debugging locally, but fails to run once published to Azure.
I enabled Organizational Authentication and selected the appropriate domain upon publishing.
The appropriate reply URL was registered
After I publish to Azure I get this error:
An unhandled exception occurred while processing the request.
OpenIdConnectProtocolException: Message contains error: 'invalid_client', error_description: 'AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'.
Trace ID: 640186d6-9a50-4fce-ae39-bbfc1caf2400
Correlation ID: 622758b2-ca52-4bb0-9a98-e14d5a45cf80
Timestamp: 2017-04-19 16:36:32Z', error_uri: 'error_uri is null'.
I'm assuming that it's because the Client Secret needs to be stored in Azure somewhere; however, the value in secrets.json did not work when I added it as an App Setting (invalid client secret error) as I saw someone was able to do on another post. Also not sure if putting the value of "Authentication:AzureAd:ClientSecret" in AzureĀ AppSettings is a good idea anyway.
Not sure if this is useful to anyone or not. But i receive a similar error message.
OpenIdConnectProtocolException: Message contains error: 'invalid_client', error_description: 'error_description is null', error_uri: 'error_uri is null'.
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler+<RedeemAuthorizationCodeAsync>d__22.MoveNext()
The solution for me was to provide a secret in the token service
,new Client
{
ClientId = "Testclient",
ClientName = "client",
ClientSecrets =
{
new Secret("secret".Sha256())
},
//Hybrid is a mix between implicit and authorization flow
AllowedGrantTypes = GrantTypes.Hybrid,
And provide the secret in the client
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
//The name of the authentication configuration.. just incase we have multiple
AuthenticationScheme = "oidc",
//Represents where to store the identity information -> which points to the cookie middleware declared above
SignInScheme = "Cookies",
//where the token service reside -> system will configure itself by invoking the discovery endpoint for the token service
Authority = "http://localhost:5000",
RequireHttpsMetadata = false,
ClientId = "Testclient",
ClientSecret = "secret",
//hybrid flow -grant type
ResponseType = "code id_token",
Hopefully this helps someone
Somehow I the Azure AD IDs needed for the proper Azure Active Directory App Registration were mixed up. There were 2 App Registration entries and the ClientID and TenentID's didn't match up with the local. So I synchronized the Client and Tenent IDs with one of the App Registration entries, and made sure the Client Secret was in App Settings, and it worked properly.
I verified these steps with this fine example Win's GitHub repository and they match now.

Resources