I can Get a Valid Token for Graph with a certificate using:
AuthenticationResult authenticationResult = await context.AcquireTokenAsync(resource, certificate);
Where
resource = "https://graph.microsoft.com"
I can do the same with my SharePoint Online with:
resource = "https://{myAAD}.sharepoint.com"
I would like to use the same token for both so I tried:
resource = "https://{myAAD}.sharepoint.com;https://graph.microsoft.com";
It did not work!
The Tenant, client ID, and the certificate are all the same for both
Is there a way to do it?
Thank you in advance
An access token is always valid for a single resource, not more.
You simply need to call the AcquireTokenAsync method twice, once for the graph, once for SharePoint.
Related
I'm trying to use AcquireTokenByAuthorizationCodeAsync to exchange code with token per below:
clientCredential credential = new ClientCredential(ConfigurationManager.AppSettings["ClientId"].ToString(), "12345");
string userObjectID = context.AuthenticationTicket?.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
var authority = "https://abc.b2clogin.com/xxx.onmicrosoft.com/XXX-SIGNINSIGNUP/v2.0";
AuthenticationContext authContext = new AuthenticationContext(authority, false, new WebSessionCache(userObjectID));
//Aquiring access_token by passing code
AuthenticationResult result = authContext.AcquireTokenByAuthorizationCodeAsync(code, new Uri(ConfigurationManager.AppSettings["azure.B2C.RedirectUrl"].ToString()), credential).Result;
However I keep getting this error:
"The resource you are looking for has been removed, had its name changed, or is temporarily unavailable."
I had a quick look at Azure AD Library below:
https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/blob/2b53bb4e641da49e9f678f32e7f7c204290a72f2/src/Microsoft.IdentityModel.Clients.ActiveDirectory/Internal/Instance/Authenticator.cs#L105
Where it doesn't seem to support the new b2clogin domains i.e. it's not supporting version and policy:
https://learn.microsoft.com/en-us/azure/active-directory-b2c/b2clogin
Any idea how this can be fixed?
You findings are correct, ADAL does not support Azure AD B2C. More importantly it's deprecated. Please move to MSAL for full Azure AD B2C support. For guidance take a look at Migrate applications to the Microsoft Authentication Library (MSAL).
I am trying to access Microsoft Office 365 Planner using CSOM and Azure App. Whenever I try to access planner using group Id i am getting the below error:
401 - Unauthorized: Access is denied due to invalid credentials. You do not have permission to view this directory or page using the credentials that you supplied.
I have given the required permissions to Azure Graph api.
Application - Read Groups All, Read and Write Groups All.
Delegated - Tasks.ReadWrite
Below is the sample code that i am using:
//Querying plans in current group await
graphClient.Groups[groupId].Planner.Plans.Request().GetAsync();
Is there any option to achieve this. I need to access the planner and need to create Buckets and plans based on Office 365 group.
Any help is much appreciated. Thanks in advance.
You should be using Microsoft Graph rather than Azure AD Graph API.
https://learn.microsoft.com/en-us/graph/planner-concept-overview
Also, you need to authenticate with your user credentials to access the Planner. You can change the GetAccessToken method to authenticate this way (example from linked blog).
private async Task<string> GetAccessToken(string resourceId, string userName, string password)
{
try
{
var authority = ConfigurationManager.AppSettings["ida:AuthorizationLoginUri"] + ConfigurationManager.AppSettings["ida:TenantId"];
var authContext = new AuthenticationContext(authority);
var credentials = new UserPasswordCredential(userName, password);
var authResult = await authContext.AcquireTokenAsync(resourceId, ConfigurationManager.AppSettings["ida:ClientIdNativeClient"], credentials);
// Get the result
return authResult.AccessToken;
}
catch (Exception ex)
{
// TODO: handle the exception
return;
}
You need to also ensure that your app is registered properly in the portal. Please check out this helpful blog that shows how to get past the error you described when accessing the planner:
https://karinebosch.wordpress.com/2017/12/18/microsoft-graph/
Is there a way to generate access token of a user using AZURE AD GRAPH client or MICROSOFT Graph client?
I have username and password ,client id, policy name. Using all these parameters. I want to generate the token.
Thanks!
We could do that but it is not recommanded that to use the username and password to do that.
In general Microsoft does not advise customers to use it as it's less secure than the other flows, and it is not compatible with conditional access (if the resource requires conditional access, the call to AcquireTokenSilent will just fail, given that this is not an interactive flow, the STS does not have an opportunity to present a dialog to the user to tell him/her that s/he needs to do multiple factor authentication).
Demo code.
var graphResourceId = "https://graph.windows.net";
var clientId = "afa0b3fxxxxx";
var userName= "xxxxx";
var password = "xxx";
var result = await authenticationContext.AcquireTokenAsync(graphResourceId, clientId, new UserPasswordCredential(userName, password));
var accessToken = result.AccessToken
For more information, please refer to this document.
Update:
Get Refresh token.
url:
post https://login.microsoftonline.com/{tenantId}/oauth2/token
Header:
Content-Type: application/x-www-form-urlencoded
body
resource=https%3A%2F%2Fgraph.windows.net&client_id=xxxxx&grant_type=password&username=tom%40xxxx.onmicrosoft.com&password=xxxxx&scope=openid
Test Result:
Edit:
I have added the "id_token" but still get an "Unauthorized" response.
Here is my login code:
PublicClientApplication myApp = new PublicClientApplication("My-AppID-From-App-Registration-Portal");
string[] scopes = new string[] { "User.Read" };
AuthenticationResult authenticationResult = await myApp.AcquireTokenAsync(scopes).ConfigureAwait(false);
JObject payload = new JObject();
payload["access_token"] = authenticationResult.AccessToken;
payload["id_token"] = authenticationResult.IdToken;
user = await MobileService.LoginAsync(MobileServiceAuthenticationProvider.MicrosoftAccount, payload);
Original Post:
Is it possible to authenticate to a App Services backend using the token retrieved from Microsoft Graph?
I have already tried using this token and calling LoginAsync() with AzureActiveDirectory as the provider, this doesn't work.
JObject payload = new JObject();
payload["access_token"] = GraphAuthenticationHelper.TokenForUser;
user = await MobileService.LoginAsync(MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory, payload);
Is this possible?
UPDATE: In my original answer, I said you cannot do this. But in reality, you can do this but it's a dangerous thing to do since anyone with a valid Microsoft Graph token could theoretically access your APIs. Before I walk you down that path, let me describe the "right" way to access the Microsoft Graph on behalf of your end user.
The right way to do this is to use the on-behalf-of flow in the mobile backend code to exchange the user's ID token for a Microsoft Graph token. The flow looks like the following:
Client initiates a login with AAD using MSAL and sets the resource to the mobile backend (not the Graph). The result should be a set of tokens.
Client uses the mobile SDK to do a login with BOTH the access_token AND the id_token from #1.
Example code:
JObject payload = new JObject();
payload["access_token"] = {access_token.from.msal};
payload["id_token"] = {id_token.from.msal};
var user = await MobileService.LoginAsync(
MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory,
payload);
The backend code exchanges the user's ID token (from the x-ms-token-aad-id-token request header) for a graph token. This token exchange is known as "on-behalf-of" and is documented here. I think this can be done using ADAL or MSAL libraries, but I wasn't able to find documentation. It's also simple enough that you could implement the HTTP protocol directly without too much trouble.
The backend uses the newly acquired MS Graph token and makes the graph API call.
You can also cache the graph token that you acquire on the backend so that each API call doesn't require more AAD API calls to do token exchange.
I think no ,please refer to document : https://learn.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-dotnet-how-to-use-client-library#a-nameauthenticationaauthenticate-users
Replace INSERT-RESOURCE-ID-HERE with the client ID for your mobile app backend. You can obtain the client ID from the Advanced tab under Azure Active Directory Settings in the portal.
The audience of the access token should be the client ID for your mobile app backend . So if resource is https://graph.microsoft.com/(aud claim in access token) , then Client-managed authentication won't work .
Going by the code provided by Microsoft (I'm assuming), I am unable to query my Azure Active Directory. Every time I call the following, I get a response of {Authorization Required.}:
ActiveDirectoryClient client = AuthenticationHelper.GetActiveDirectoryClient();
IPagedCollection<IUser> pagedCollection = await client.Users.ExecuteAsync();
I'm new to Azure Active Directory and I'm new to the Graph and thought that the samples provided would function. They do not and I am hoping someone here can tell me either what is wrong with the code or how do I grant myself authorization to my own directory? I thought the AccessKey would be the authentication method, but apparently that's useless as it's not used in their examples.
Basically, to call the REST which protected by Azure AD which support OAuth2.0 to authorize the third-party application, we need to pass a bearer token.
And to go through the code sample, please ensure that you followed the steps list by the README.md.
Note: there is something not clear in the README.md about config the permission. The code sample is using the Azure AD Graph instead of Microsoft Graph, we need to choose the Windows Azure Active Directory instead of Microsoft Graph. And I have report this issue here.
You can see that there is a static filed named token in class AuthenticationHelper which will be set the value when the users sign-in using the code in Startup.Auth.cs like below:( not using cert)
// Create a Client Credential Using an Application Key
ClientCredential credential = new ClientCredential(clientId, appKey);
string userObjectID = context.AuthenticationTicket.Identity.FindFirst(
"http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
AuthenticationContext authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectID));
AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId);
AuthenticationHelper.token = result.AccessToken;
And here is the detail progress to acquire the token via the OAuth 2.0 code grant flow:
More detail about this flow you can refer here.