How to access Microsoft Office 365 Planner programmatically - azure

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/

Related

How to get profile image from Azure Active Directory using Microsoft Graph?

I am implementing Microsoft Azure Active Directory authentication using Microsoft Graph and OAuth2 using this tutorial.
Here is my call which fetches me the displayName, givenName, surName, mail, etc.
$graph = new Graph();
$graph->setAccessToken($accessToken->getToken());
$user = $graph->createRequest('GET', '/me?$select=displayName,givenName,surName,mail,mailboxSettings,userPrincipalName')
->setReturnType(Model\User::class)
->execute();
$fname = $user->getGivenName();
$mail = $user->getMail();
Now using the same call, how can I fetch profile image of the user? I don't want to make a separate API call, but want to fetch the photo in same call.
How can I get the profile image?
You cant get users profile image from AAD id token.
The best way of getting the picture is through MS Graph.
In MS Graph API, you can use the below endpoint to fetch photo from Azure AD:
https://graph.microsoft.com/v1.0/users/{id | userPrincipalName}/photo/$value
To get this, you need to set the app permission as
To Get profile picture you need at least one of the following
permissions User.ReadBasic.All; User.Read.All; User.ReadWrite.All
C# code sample:
public static async Task<System.Drawing.Image> GetMePhotoAsync()
{
try
{
// GET /me
Stream photoresponse = await graphClient.Me.Photo.Content.Request().GetAsync();
if (photoresponse != null)
{
MemoryStream ms = new MemoryStream();
photoresponse.CopyTo(ms);
System.Drawing.Image i = System.Drawing.Image.FromStream(ms);
return i;
}
else
{ return null; }
}
catch (ServiceException ex)
{
Console.WriteLine($"Error getting signed-in user profilephoto: {ex.Message}");
return null;
}
}
Reference:
Azure AD Get photo
Upon your code in the question, I searched for the Microsoft document and found no way to get profile image by using the same call you provided. And according to the document, we can find that the api of 'List user' can just providing these properties. To prove this conclusion, I also read the document about creating user and updating user, they all showed that profile image is not supported by this api.
For how to get profile image via api, #Hari Krishna has provided solution and document.

Accessing Google Drive through Azure Function

The task is to download google sheet in excel format and store it in Azure blob storage on timely basics using the Azure time trigger function.
Access Method to users google drive - OAuth Client ID.
I have created an Azure function locally and it works fine as expected and performs the task but when I deploy azure function I get this error.
Code for DriveService where the error occurs according to stack trace when deployed
public string[] Scopes = { DriveService.Scope.Drive, DriveService.Scope.DriveReadonly };
public DriveService GetService()
{
UserCredential _credential;
//Error Occurs at line below
Google.Apis.Auth.OAuth2.Flows.GoogleAuthorizationCodeFlow googleAuthFlow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer()
{
ClientSecrets = new ClientSecrets
{
ClientId = _config[Constant.ClientId],
ClientSecret = _config[Constant.ClientSecret],
}
});
string FilePath = Path.GetDirectoryName(_driveCredentialsPath);
_credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
googleAuthFlow.ClientSecrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(FilePath, true)).Result;
DriveService service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = _credential,
ApplicationName = Constant.ApplicationName,
});
return service;
}
I think there are two situations where it can go wrong but I am not sure about it.
When I am running the application locally a consent screen appears and gives permission to access the drive.
When this same function is running on azure who and how it will grant permission to access the drive.
I have provided my Azure App URL on Google OAuth Consent Screen as mentioned below to overcome this situation.
When I am running locally after giving permission to access drive it creates a TOKENRESPONSE-USER file a which consists of the access token, expiry date refresh token, and scope.
Is this possible that when the function is deployed it is unable to create a TOKENRESPONSE-USER file on azure function?
Please let me know why I am getting this error or do I need to change something in my process.
You can configure your function app to use Google login for authentication purposes when running on Azure. To achieve this you have to generate client id and client secret using the Google sign-in for server-side apps, using this connection you can store the tokens obtained in the token store. Please refer to this document to configure your function app to use Google Login, refer to this document regarding the token store and how to retrieve and refresh the token obtained.

Scope needed to get access token to pull user groups from Azure using client id and client secret and graph API

I am trying to get the groups in my azure tenant using my client secret and client id. Problem is I don't know what scope to pass when getting an access token to use the graph api. I used https://graph.microsoft.com/.default to get an access token but this doesn't include permission to pull groups. What's the appropriate scope to use
https://learn.microsoft.com/en-us/graph/api/group-list?view=graph-rest-1.0#permissions
Permissions
One of the following permissions is required to call this API. To learn more, including how to choose permissions, see Permissions.
Permission type Permissions (from least to most privileged)
Delegated (work or school account) Group.Read.All, Group.ReadWrite.All
Application Group.Read.All, Group.ReadWrite.All
You need to configure the API access within AAD, not with the scope. Make sure that you don't forget to click on "grant permissions".
Example assumes that you require application permission. Delegated permission works similarly.
Sample code for getting the data using MSAL for authentication:
IConfidentialClientApplication app = new ConfidentialClientApplication(
"clientId",
"https://login.microsoftonline.com/yourtenant.onmicrosoft.com",
"http://localhost (redirecturi)",
new ClientCredential("secret"),
new TokenCache(), new TokenCache());
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
try
{
AuthenticationResult result = await app.AcquireTokenForClientAsync(scopes);
System.Console.WriteLine(result.AccessToken);
using (var http = new HttpClient())
{
http.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", result.AccessToken);
var groupResponse = await http.GetAsync("https://graph.microsoft.com/v1.0/groups");
var groupJson = await groupResponse.Content.ReadAsStringAsync();
System.Console.WriteLine(groupJson);
}
}
catch (Exception ex)
{
System.Console.WriteLine(ex.Message);
}

Status: Unauthorized (401) error while getting the reports from the workspace

I have created my app and registered over https://dev.powerbi.com/Apps as Native. In Azure, I added myself ad global admin user, registered myself to the application as admin, granted all Power BI API permissions. I created a workspace, added myself an admin user. Uploaded a Power BI report in my workspace. Works well when I am on browser.
I am trying to connect my report by using ASP.NET 4.61 MVC. My credentials, username and password work, so no problem for this code below:
var credential = new UserPasswordCredential(Username, Password);
// Authenticate using created credentials
var authenticationContext = new AuthenticationContext(AuthorityUrl);
var authenticationResult = await authenticationContext.AcquireTokenAsync(ResourceUrl, ApplicationId, credential);
if (authenticationResult == null)
{
result.ErrorMessage = "Authentication Failed.";
return View(result);
}
var tokenCredentials = new TokenCredentials(authenticationResult.AccessToken, "Bearer");
However, I am receiving the error: Status: Unauthorized (401) on the line GetReportsInGroupAsync(Workspaceid); where workspaceId is matching with my workspace.
// Create a Power BI Client object. It will be used to call Power BI APIs.
using (var client = new PowerBIClient(new Uri(ApiUrl), tokenCredentials))
{
// Get a list of reports.
var reports = await client.Reports.GetReportsInGroupAsync(WorkspaceId);
...
}
So the reports from my workspace I cannot reach because of unauthorization error, and I could not pass it. How can I authorize myself, I am already in AAD as Global Admin, added myself as application owner and in workspace I am already registered as admin.
I've found this topic below, but the answer did not fix my issue:unauthorized error 401 for power reports embedding
Followed this guideline, also did not work: https://learn.microsoft.com/en-us/power-bi/developer/register-app
Any help would be appreciated.
I had exact the same issue, and I checked the API call's header X-PowerBI-Error-Info. What I found there was: ServicePrincipalIsNotAllowedByTenantAdminSwitch.
So, your's tenant's admin should switch on "Allow service principals to use with Power BI APIs" and apply it to security group where Service Principal resides:
Admin portal

Can't access the calendars in office365 groups

I got Unauthorized when calling to get Calendar in the Microsoft graph API, I use this verification to retrieve an access token.
I think the problem is that when I want to retrieve the Get HTTP request on Calendar the access token isn't created with credentials which result in the Unauthorized call. How can I change my code to be able to send Credentials with it and get a better Token with more privileges?
In the Azure portal, I granted all permissions to see whether that the application permissions weren't set correctly.
AuthenticationContext authenticationContext = new AuthenticationContext(authString, false);
ClientCredential clientCred = new ClientCredential(_azureAd_ClientId, _azureAd_SecretKey);
string tokenResult;
AuthenticationResult authenticationResult;
try
{
authenticationResult = await authenticationContext.AcquireTokenAsync(_azureAd_GraphResource, clientCred);
var user = authenticationResult.UserInfo;
string_token = authenticationResult.AccessToken;
tokenResult = JsonConvert.SerializeObject(authenticationResult);
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex.InnerException);
}
Reading through the comments it seems that you may need to trigger a new consent prompt in order to grant the application the permissions you have re-configured. If this is a V1 app, you can do so by adding prompt=admin_consent to the end of your request. If this is a V2 app, you will want to use the /adminconsent endpoint. More info on that is here.
There is also some more documentation on admin consent in general here.

Resources