Unable to access users calendar using application daemon token - microsoft-graph-api

I have been trying to access a user's data using the MS graph API. I have been following the official documentation and I have correctly configured the apps and the permission.
I am also following this code_sample and using this I have been able to fetch the daemon token for the application.
Using the token I am able to successfully fetch the data against the following endpoint:
https://graph.microsoft.com/v1.0/users/204e3e4f-xxxx-xxxx-xxxx-509934e1
The data looks like:
{"#odata.context":"https://graph.microsoft.com/v1.0/$metadata#users/$entity","businessPhones":[],"displayName":"developers#outlook.com Tiwari","givenName":"developers#outlook.com","jobTitle":null,"mail":null,"mobilePhone":null,"officeLocation":null,"preferredLanguage":null,"surname":"Tiwari","userPrincipalName":"developers_outlook.com#EXT##webdevelopers.onmicrosoft.com","id":"204e3e4f-x-xxxxx-xxxxxxx-509934e14fa8"}
However, I can't fetch any more data than this. All the other endpoints throw a 401 Unauthorised exception even when I have checked all the Application permission for my app.
I am trying to hit the following endpoints for fetching calendar of the above user:
https://graph.microsoft.com/v1.0/users/204e3e4f-xxxx-xx-xxxxz-509934e14fa8/calendar
https://graph.microsoft.com/v1.0/users/204e3e4f-xxx-xxx-xxxxx-509934e14fa8/calendars
both of these give 401.
Can someone suggest if I am missing something. I even decompiled my jwt token and it clearly shows all the following scopes added:
"roles": [
"Schedule.ReadWrite.All",
"OnlineMeetings.Read.All",
"Mail.ReadWrite",
"OnlineMeetings.ReadWrite.All",
"User.ReadWrite.All",
"Calendars.Read",
"Mail.ReadBasic.All",
"Files.ReadWrite.All",
"User.Read.All",
"Schedule.Read.All",
"Files.Read.All",
"Organization.ReadWrite.All",
"Mail.Read",
"Calendars.ReadWrite",
"Mail.Send",
"Organization.Read.All",
"Mail.ReadBasic"
],
Please help.

To get access to calendar events you should call the following endpoint:
GET /users/{id | userPrincipalName}/events
The documentations for calendars is here: https://learn.microsoft.com/en-us/graph/api/user-list-events

From your comment on Chris Johnson's answer, you're using a personal account. App-only tokens won't work to access a personal account, and you shouldn't be able to even obtain one using a personal account, since there's no concept of an admin.
App-only requires an admin to consent, and when she does, she grants access to all resources in her tenant. Personal accounts are not in work/school tenants, so they aren't in scope. Even if you've added that personal account as a guest in the work/school tenant, their calendar is hosted outside of the tenant, and is off limits.

Related

Microsoft Graph API Beta - Get Chat returns 401 Unauthorized

I am testing Get Chat Microsoft Graph API (which is still in Beta) and it seems to work successfully when it is called from Graph Explorer (which uses an user token), instead when I call this API from Postman with an application token, I get 401 Unauthorized with an Unknown Error as response.
https://graph.microsoft.com/beta/users/<user-id>/chats/<conversation-id>
My App Registration on Azure has these permissions:
And the decoded application token contains:
"aud": "https://graph.microsoft.com",
"roles": ["User.Read.All", "Chat.Read.All" ]
The same token it works for the Get User API
https://graph.microsoft.com/beta/users/<user-id>
Basically, it seems to have problems only the GET Chat API when called with an application token, although the documentation says it is supported. Am I missing something in the App Registration configuration?
EDIT
As I have already explained in the comments, this question doesn't help me, since:
audit is correct
permissions are present in the token and are granted by the admin in the App registration
scope is correct
Should I check something else?
Have you seen this message on the (English) documentation page?
Before calling this API with application permissions, you must request access. For details, see Protected APIs in Microsoft Teams.
It seems like Microsoft has implemented an extra layer of security for apps accessing "Teams" endpoints.

Get Azure AD directory users in a Rails app

I have a Rails 6 application and I want to use Azure Active Directory as an authentication system (with open id connect, saml2 and ldap).
The authentication is done.
Now I am trying to display user information like names or email addresses. I also want to be able to export all users of a directory.
I have tried to set a configuration up like so:
In my Rails app, in the admin panel, an admin can configure Azure AD for my application
in the config, the admin copies and pastes the configuration link provided by Azure AD (a JSON response)
Then, copies and pastes the app client_id
Then, the tenant_id (directory id)
Here is a piece of code that I expected to work:
def update_oidc
identity_provider = IdentityProvider.find_by(provider_type: 'open_id_connect', id: params[:id])
client_id = params[:client_id].strip
metadata_url = params[:metadata_url].strip
tenant_id = params[:tenant_id].strip
metadata = HTTParty.get(metadata_url).parsed_response
identity_provider.update(config: {
metadata: metadata,
metadata_url: metadata_url,
client_id: client_id,
tenant_id: tenant_id,
})
if tenant_id
directory_access_url = "https://graph.windows.net/#{tenant_id}/users?api-version=1.6"
result = HTTParty.get(directory_access_url).parsed_response
identity_provider.directories.find_or_create_by(tenant_id: tenant_id).update(
business_phones: result["business_phones"],
display_name: result["display_name"],
given_name: result["given_name"],
job_title: result["job_title"],
email: result["user_principal_name"],
mobile_phone: result["mobile_phone"],
office_location: result["office_location"],
surname: result["surname"]
)
end
redirect_to identity_provider
end
As the tenant_id is the directory id, i thought that we might be able to access user info this way (and following the Microsoft Docs). The thing is, it doesn't work because even though I'm connected to my Azure AD directory in my app, when I run result = HTTParty.get(directory_access_url).parsed_response, i have an authentication error telling me the token has expired or that i need to be connected.
I don't want to use PowerShell or anything like this. I want to be able to access directories data through my app.
Can someone tell me what i'm doing wrong or come up with an idea ?
Thanks
Just according to your code, I think you want to get the collection of users via the Azure AD Graph REST API Get users using jnunemaker/httparty library.
However, it seems to be missing the required header Authorization with its value like Bearer eyJ0eX ... FWSXfwtQ as the section Authentication and authorization of the offical document Operations overview | Graph API concepts said. Meanwhile, you have done the authentication with OpenID Connect, but Azure AD Graph API requires the access token as Authorization value from OAuth2 as the content below said.
The Graph API performs authorization based on OAuth 2.0 permission scopes present in the token. For more information about the permission scopes that the Graph API exposes, see Graph API Permission Scopes.
In order for your app to authenticate with Azure AD and call the Graph API, you must add it to your tenant and configure it to require permissions (OAuth 2.0 permission scopes) for Windows Azure Active Directory. For information about adding and configuring an app, see Integrating Applications with Azure Active Directory.
Azure AD uses the OAuth 2.0 authentication protocol. You can learn more about OAuth 2.0 in Azure AD, including supported flows and access tokens in OAuth 2.0 in Azure AD.
So I'm afraid you have to get the access token manually via OAuth2 for Azure AD again for using Graph API, or just simply refer to the sample code samples/authorization_code_example/web_app.rb using the adal library of GitHub repo AzureAD/azure-activedirectory-library-for-ruby for Ruby.

Access is denied returned when calling /me/messages

I am currently trying to make REST calls to get mailbox message stats for a particular account (i.e. read/unread count). I have done this in the Microsoft Graph Explorer and have managed to get the relevant User.Read and many other non-admin permissions.
When I try to replicate this process in Postman, I get "Access is denied. Check credentials and try again.". I followed this guide right until here where I can't move forward despite the correct permissions.
Even my token generation response contains the "scope": "User.Read"
I just want to make a call to GET https://graph.microsoft.com/v1.0/me/messages
The registered app is the account of the email I am trying to monitor. I can make this call successfully Graph Explorer, but I am unable to replicate the results with Postman, PowerShell, or groovy
To make a request to read the signed-in user's mail (GET .../me/messages), your application needs the delegated permissions (i.e. scope) Mail.Read. Just having User.Read is not sufficient. This is also described in the documentation: https://learn.microsoft.com/en-us/graph/api/user-list-messages?view=graph-rest-1.0
It turned out Delegated Permissions weren't enough, despite the fact that it was what I understood my circumstance.
It only started working after I gave it APP Permissions

Retrieving All User Wallets through Coinbase iOS SDK

I've recently been experimenting with the Coinbase iOS SDK and I've been having issues retrieving a user's Ethereum, Litecoin and Bitcoin Cash balances and historic transactions. Currently, I've only managed to do this with Bitcoin, USD and EUR, which seems to be consistent with the behaviour of the demo app supplied by Coinbase.
I have configured an application on the Coinbase API Access page using OAuth2 and the generated client ID and secret are being used within the app.
The issue seems to stem from the fact that I modified the Coinbase iOS SDK to allow me to pass the account parameter as
‘all’. This, I had hoped, would allow me to view details of all user accounts (ETH, BTC, LTC etc.) however, I only get BTC, USD and EUR when calling ‘getAccountsList’ on the Coinbase object.
NSString *accessToken = [response objectForKey:#"access_token"];
Coinbase *client = [Coinbase coinbaseWithOAuthAccessToken:accessToken];
[client getAccountsList:^(NSArray *accounts, CoinbasePagingHelper *paging, NSError *error) {
for (CoinbaseAccount *account in accounts) {
// Only BTC, USD and EUR are in the accounts array at this point.
}
}];
This is surprising as the permissions request page correctly asks the user for all wallets, as you can see in the screenshot below:
I suspect a solution to this would be to use API keys, as you are able to specify exactly which accounts to grant access to. I plan to distribute the app however, so this technique should not be used.
Here is an example of the URL I am sending:
https://www.coinbase.com/oauth/authorize?response_type=code&client_id=CLIENT_ID_GOES_HERE&account=all&scope=balance%20transactions%20user&redirect_uri=com.example-name.example-app.coinbase-oauth%3A%2F%2Fcoinbase-oauth
Does anyone know how I can request access to all of a users accounts using OAuth and be able to retrieve details for each? Is the scope I defined incorrect in some way? The only alternative I can think of would be to request access one by one to each wallet and store individual access tokens. This wouldn't be a great user experience however.
Thanks!
Add the parameter
account=all
to the oAuth endpoint: https://coinbase.com/oauth/authorize?account=all&response_type=code.‌​..
Here are the details: https://developers.coinbase.com/docs/wallet/coinbase-connect/permissions
Coinbase Connect applications can request different access to user’s wallets. This access is defined by account parameter on OAuth2 authorization URL. Available options are:`
select - (default) Allow user to pick the wallet associated with the application
new - Application will create a new wallet (named after the application)
all - Application will get access to all of user’s wallets
I believe the iOS SDK is in need of an update. It still connects to old API version.
I'm using the original Coinbase SDK. No fork. in stead, next to the wallet:accounts:read scope, I also add ["accounts": "all"] as meta argument to the startAuthentication method.
AND. I am NOT using the getAccountList method, but instead the more general .doGet method with the api v2 accounts endpoint (so coinbase.doGet("https://api.coinbase.com/v2/accounts", parameters: nil) {(response, error) -> Void in
This gives me account info for all wallets. You do need to do some json processing on the response object in this case though.
First if you don't have one, you need to create an account on Coinbase
Then, please take a look first on the Coinbase digital api documentation, and I agree with you that it maybe easier to use the API to get data (if the target account is only your own personal account)
Because according to Coinbase:
API Key authentication should only be used to access your own account or merchant orders. If your application requires access to other Coinbase users’ accounts, do not use API Key. To securely access other Coinbase users’ accounts, use Coinbase Connect (OAuth2)
You have two possibilities:
USE API
Assuming user has grant wallet:accounts:read to the API key ( which allow you to List user’s accounts and their balances) according to the wallet permission documentation.
Once done, you may use the official wallet client libraries for iOS - coinbase is available through CocoaPods - by adding the following line to your Podfile: :
pod "coinbase-official"
USE OAuth2 PROTOCOL
According to this,
It is a slightly more complex integration than the API Key authentication method, but is more flexible. OAuth2 works well for web applications, as well as desktop and mobile apps.
You will find a lot of informations in the coinbase-connect integrating documentation, and you may also take a look on the official OAuth2 protocol website first.
Assuming you are OK with OAuth2, you will also have to ask user to grant you permission before requesting data.
As you need access to user wallet, you still have to request access token and add a scope parameter in the authorization request (Comma separated list of permissions (scopes) your application requests access to), if you need to see the full scopes list please refer yourself to this page.
The required scope is the same as API method: wallet:accounts:read, and your request will look like this:
GET https://www.coinbase.com/oauth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URL&state=SECURE_RANDOM&scope=wallet:accounts:read
After a successful request, a valid access token will be returned in the response (like this):
{
"access_token": "6915ab99857fec1e6f2f6c078583756d0c09d7207750baea28dfbc3d4b0f2cb80",
"token_type": "bearer",
"expires_in": 7200,
"refresh_token": "73a3431906de603504c1e8437709b0f47d07bed11981fe61b522278a81a9232b7",
"scope": "wallet:user:read wallet:accounts:read"
}
Once you get the access token, you can make any API call corresponding to the previous scope if you add the following header to the request:
Authorization: Bearer 6915ab99857fec1e6f2f6c078583756d0c09d7207750baea28dfbc3d4b0f2cb80
Finally, you may refer to the API reference documentation to see all possible API call and the relative scopes.
To conclude, you need to grant permission, then list the user accounts, then you may get any account resource:
Account resource represents all of a user’s accounts, including bitcoin, bitcoin cash, litecoin and ethereum wallets, fiat currency accounts, and vaults.
Regards
Still no luck.
Tried with adding param account=all. It gave me access to all wallets (exactly same as op). However, in code, I can only get BTC Wallet, BTC Vault, EUR Wallet and newly created BTC Wallet. The new wallet was created by adding param account=new.
Tried with adding param account_currency=BTC,ETH and chose ETH Wallet on oAuth authorization. Did getAccountsList which returned 0 objects and no errors from the server.
Tried with revoking all API application access in my Coinbase account (Settings->Security).
Scope: balance transactions user
Endpoint: .../oauth/authorize?account=all&response_type=code&client_id=%...

Is it possible to obtain a Mail.ReadWrite scope access token from the microsoftonline oauth2 endpoint using grant_type=password?

I have an application registered with https://apps.dev.microsoft.com with Microsoft Graph Permissions including: Mail.ReadWrite, Mail.ReadWrite.Shared, and User.Read. Ultimately, I need to read mail and move it to other folders using a daemon task. I am using the Microsoft OAuth2 endpoint to obtain an access token using grant_type=password. This call is working in that I get back a token with scope=Mail.Read, but I need Mail.ReadWrite. Is it possible to obtain a Mail.ReadWrite token using grant_type=password?
My call looks like this:
resource=<myresource>&client_id=<myclientid>&grant_type=password&username=<myusername>&password=<mypassword>&scope=openid
I have also tried altering the scope to include Mail.ReadWrite, but that does not seem to work.
I managed to get this working. After editing permissions for the application, there must have been a window of time where the settings did not yet take effect. I manually signed into my app a few more times and was eventually prompted to accept the new permissions. The next time I made the OAuth request, I got back a Mail.ReadWrite token.

Resources