Azure Active directory Sharepoint & Graph API - azure

I am in a bit of confusion how to get a bearer token that will work for a sharepoint sites as well as the graph api.
We are using MFA (Multi factor authentication) so we get a text message when the user tries to login. This all works and we get a token back but the resource I am pointing to is https://srmukdev.sharepoint.com/, how can we use this token to access the https://graph.microsoft.com/ api.
At the moment it doesn't work. I can make separate login requests, but we dont want to do this as it's required to access both parts with the same token? is there a method that can translate one token to another? something that works at least?
You can see the current difference is the ResourceUrl
The sharepoint api details I use
<add key="ida:AADInstance" value="https://login.microsoftonline.com/{0}" />
<add key="ida:Tenant" value="srmukdev.onmicrosoft.com" />
<add key="ida:ApplicationId" value="000000-0000-0000-0000-0000000" />
<add key="ida:RedirectUri" value="http://someuri/" />
<add key="ida.ResourceUrl" value="https://srmukdev.sharepoint.com/" />
The graph api details I use
<add key="ida:AADInstance" value="https://login.microsoftonline.com/{0}" />
<add key="ida:Tenant" value="srmukdev.onmicrosoft.com" />
<add key="ida:ApplicationId" value="000000-0000-0000-0000-0000000" />
<add key="ida:RedirectUri" value="http://someuri/" />
<add key="ida.ResourceUrl" value="https://graph.microsoft.com/" />
Many thanks

Let's start by saying that you cannot get a token which will work for both the Microsoft Graph API and the SharePoint API directly. Tokens are created with specific audiences, and as a part of token validation by the Web API, they will check that the audience of the token matches their unique identifier.
I think one possible solution here is to realize that the Microsoft Graph token already gives you access to the SharePoint API. See the documentation here. You should be able to get a token for just the Microsoft Graph, and then use the Microsoft Graph specific endpoints to get data from your SharePoint. This is one of the problems the Microsoft Graph is trying to solve. A single endpoint and token to access all of your Microsoft data.
Another solution is to use the authorization code you receive to request two tokens to the two different endpoints. Depending on what libraries you are using, and the specific flow you are following, this may be harder than not to accomplish, but in general, the authorization code grant flow is used to sign in a user. After the user is redirected to the Microsoft Login Page, and then successfully signs in, your service receives an authorization code, which it then exchanges for an access token using the Token Endpoint. This authorization code can be used to get an access token for any resource the client has been configured to call, so you can call the token endpoint twice, with two different resource values, and get back two access tokens. I do this in one of my Python/Flask samples.
Finally, assuming you got back an access token and refresh token for a particular resource, you could then use the refresh token to get a token for a different resource the app has been authorized for.
The refresh token issued by Azure AD can be used to access multiple
resources. For example, if you have a client application that has
permission to call two web APIs, the refresh token can be used to get
an access token to the other web API as well.
See here for a look at how to do this.

Related

Azure Apim authentication for apis

I have an api endpoint which is being used by multiple public clients. And each client is configured with different clientids. I am using Authorization Code flow with Oauth2 openid protocol. I would like to introduce an Azure Apim service and would like to validate the jwt token before forwarding the request to apis. Could you please let me know how can i achieve this?
Note: I can't use single client id as redirect uri is different for each client.
You can use the Validate JWT policy to pre-authorize requests in API Management, by validating the access tokens of each incoming request. If a request does not have a valid token, API Management blocks it. For example, add the following policy to the <inbound> policy section of the Echo API. It checks the audience claim in an access token, and returns an error message if the token is not valid.
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid.">
<openid-config url="https://login.microsoftonline.com/{aad-tenant}/.well-known/openid-configuration" />
<required-claims>
<claim name="aud">
<value>{Application ID of backend-app}</value>
</claim>
</required-claims>
</validate-jwt>
For more details, you could refer to the article about Configure a JWT validation policy to pre-authorize requests

Azure API Management: authorization with Oauth2 401 gives "Unauthorized. Access token is missing or invalid."

I have a few APIs (Logic Apps, Functions) that I want to expose through Azure API Management.
They work fine, so I decided to add OAuth2 autorization.
I followed step by step https://learn.microsoft.com/fr-fr/azure/api-management/api-management-howto-protect-backend-with-aad:
Register an application (backend-app) in Azure AD to represent the API.
Register another application (client-app) in Azure AD to represent a client application that needs to call the API.
In Azure AD, grant permissions to allow the client-app to call the backend-app.
Configure the Developer Console to call the API using OAuth 2.0 user authorization.
Add the validate-jwt policy to validate the OAuth token for every incoming request.
Also use Postman to test
Everything works until the "validate-jwt" policy step.
When I add it, I get a "401 - Unauthorized. Access token is missing or invalid."
I can get the token, in Developer Console and Postman, but as soon as I do the API call... 401!
When I used jwt.ms to check the content of the token, I noticed that the aud param has nothing to do with the backend Application ID.
The value in the token is "00000003-0000-0000-c000-000000000000", whereas the backend app ID is like "16caXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXc0".
I'm running out of ideas and need the help of some Azure gurus out there!
Help would be very much appreciated...
Here below the inbound policy as per the MS doc:
<policies>
<inbound>
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid.">
<openid-config url="https://login.microsoftonline.com/MY_AD_TENANT_ID/.well-known/openid-configuration" />
<required-claims>
<claim name="aud">
<value>MY8BACKEND_APP_ID_GUID</value>
</claim>
</required-claims>
</validate-jwt>
</inbound>
<backend>
<forward-request />
</backend>
<outbound />
<on-error />
</policies>
Screen cap of the Postman screen where I get the token (this works, but then when I send the request --> 401)
Screen cap of aud param in jwt.ms
I had some problems with validating Azure AD tokens a couple of years back - see my write up.
I suspect the problem is the nonce in the JWT header.
You're not really required to check value of aud parameter. You could remove required-claims alltogether, this way token presence and signature would still be validated. If you want to make sure that token was issued for your app, just find the claim that contains app id and use it in name="..." to match against your app id value.
if using v2 version endpoint, go to -> azure ad -> app registration -> select backend-app -> manifest -> update property "accessTokenAcceptedVersion": 2,"

AADSTS700016: UnauthorizedClient_DoesNotMatchRequest

Not sure if this is the right place to ask but... We have an older application that is set up to use SSO, currently Azure ADFS. I want to use login.microsoft.com url instead of our organizational url that has been used in the past.
I replaced the currently working links in web.config with the endpoints from Azure
<appSettings>
<add key="FederationMetadataLocation" value="https://login.microsoftonline.com/dfmi.onmicrosoft.com/FederationMetadata/2007-06/FederationMetadata.xml" />
</appSettings>
and
<federatedAuthentication>
<wsFederation passiveRedirectEnabled="true" issuer="https://login.microsoftonline.com/0845a734g7-6d23-7c96-9f4x-3427v39n4sd5/wsfed/" realm="https://customdfmi.dfmi.net/" requireHttps="true" />
<cookieHandler requireSsl="false" />
</federatedAuthentication>
I get to the sign-in page. When I put in the credentials it shows "AADSTS700016: Application with identifier 'https://customdfmi.dfmi.net/' was not found in the directory".
It is set up in Azure. Redirect URI is the exact copy of what's in web.config. What am I putting wrong in web.config? Do I need to put the Application ID somewhere in it? Any pointers would be great. Thanks!
Did you received this message?
AADSTS700016
UnauthorizedClient_DoesNotMatchRequest - The application wasn't found in the directory/tenant.
This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have misconfigured the identifier value for the application or sent your authentication request to the wrong tenant.

ADALjs and Azure AD auth for Wep API project

I have a client app and Web API app hosted on different domains and want to utilize ADAL.js in my client app to login in my Web API app, but still getting Unauthorized error.
In web api web.config I've specified my AAD details:
<add key="ida:AudienceUri" value="http://clientappurl/" />
<add key="ida:FederationMetadataLocation" value="https://login.windows.net/...3596365/federationmetadata/2007-06/federationmetadata.xml" />
<add key="ida:ClientId" value=".....388ffcc3" />
<add key="ida:ClientSecret" value="....gBsD7o=" />
<add key="ida:Tenant" value="........onmicrosoft.com" />
<add key="ida:TenantId" value="........96365" />
<add key="ida:Auth" value="https://login.windows.net/" />
<add key="ida:GraphUrl" value="https://graph.windows.net" />
And updated Startup.Auth.cs with following:
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = "http://myclientapp",
Tenant = "developertenant.onmicrosoft.com",
AuthenticationType = "OAuth2Bearer",
});
On the client I've specified endpoints (my api url), tenant and clientId. ADALjs redirects user to microsoft login page and looks like after sucessfull login it writes some data to local storage. But API app still respondes with Unauthorized error.
Are there any tutorials on how properly configure wep api and client apps hosted on different domains to utilize AAD?
How can I read authorized user details like AAD user group from my Web API app?
Here is an example which shows how to read AAD group claims from a web app:
https://github.com/Azure-Samples/active-directory-dotnet-webapp-groupclaims
Once you have the tokens, you can then call a Web API, which is shown by this example:
https://github.com/Azure-Samples/active-directory-dotnet-webapp-webapi-openidconnect
There's a good list of AAD examples here:
https://azure.microsoft.com/en-us/documentation/articles/active-directory-authentication-scenarios/

The provided anti-forgery token was meant for user "UserName", but the current user is ""

When I am login with user's credential, first time no error while login to application,
but when I logoff and again login with other user's credential got an error
The provided anti-forgery token was meant for user "UserName", but the current user is "".
I am implementing AntiForgoryToken and IPrincipal with asp.net mvc 5
I tried :
AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; in Application_Start()
I already refered this link When attempt logoff, The provided anti-forgery token was meant for user "XXXX", but the current user is ""
How can I fix this error ?
Thanks in advance.
I found my IIS instance had both Anonymous and Windows authentication enabled which was causing this exception for my application
Authentication Settings both enabled
This setting seems to be the cause of this exception. It seems that the ValidateAntiForgeryToken action filter was using the current user populated with an empty string in the Anon authentication and then attempting to match it against the token which was populated using Win authentication.
By turning off either Windows or Anonymous authentication (for my application I switched off Anon authentication,) the tokens now match up.
Authentication Settings one enabled
This setting can be altered in IIS manager or in the web.config file like so
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="false" />
<windowsAuthentication enabled="true" />
</authentication>
</security>
</system.webServer>
You don't really need to check for the antiforgery token on the post method of your login.
Antiforgery tokens provide protection from CSRF attacks. A CSRF attack happens when a malicious script/link posts an HTTP request on your behalf without your knowledge or consent. When an antiforgery token is embedded on your page, the server can check for this token when it receives the request to verify that the request indeed came from the page. A request from a malicious script or link will not have the token and will fail.
So, all other post actions that you want to protect should be decorated them with the [Authorize] and [ValidateAntiForgeryToken] attributes. The login post method, however, doesn't need either of these attributes.
Update: It is really needed. See answer in Stephen Muecke's comment.

Resources