How to use Microsoft.Graph with client authorization and not get a 401 - azure

We have
created Azure Active Directory
created a new Application
registered the new Application in Azure AD
given ALL the permissions to the API
granted admin permissions
Now we login with this app credentials
We get authorization:
GET /1111111-aaaa-4fd3-bf32-9bfc460f67b1/oauth2/v2.0/authorize HTTP/1.1
Host: login.microsoftonline.com
cache-control: no-cache
Postman-Token: 111111-aaaa-4696-9828-9110670706c5
We get the token:
POST /11111111-aaaa-4fd3-bf32-9bfc460f67b1/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
cache-control: no-cache
Postman-Token: 11111111-aaaa-47e4-b2fb-6b94cd02312a
client_id=11111111-aaaa-482e-ab17-86e4c2c6240c
scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
client_secret=aaaaaaaaaaaDJk6jBJ%2FuBRJM6AFxyFIDMKn867hmvU%3D
grant_type=client_credentials
The token analyzed with jwt.io:
{
"aud": "https://graph.microsoft.com",
"iss": "https://sts.windows.net/1111111-ccc6-4fd3-bf32-9bfc460f67b1/",
"iat": 1541603660,
"nbf": 1541603660,
"exp": 1541607560,
"aio": "42RgYFB+/Gyh8uF3yl+uKU7km//kFwA=",
"app_displayname": "ToDoListService",
"appid": "1111111-4e99-482e-ab17-86e4c2c6240c",
"appidacr": "1",
"idp": "https://sts.windows.net/1111111-ccc6-4fd3-bf32-9bfc460f67b1/",
"oid": "1111111-98fb-4a47-af7f-d3800dde2f7b",
"roles": [
"Chat.UpdatePolicyViolation.All",
"Calls.JoinGroupCall.All",
"EduRoster.Read.All",
"OnlineMeetings.Read.All",
"Mail.ReadWrite",
"OnlineMeetings.ReadWrite.All",
"Device.ReadWrite.All",
"User.ReadWrite.All",
"Domain.ReadWrite.All",
"Application.ReadWrite.OwnedBy",
"SecurityEvents.Read.All",
"Calendars.Read",
"EduAssignments.ReadWrite.All",
"People.Read.All",
"Application.ReadWrite.All",
"Calls.InitiateGroupCall.All",
"Group.Read.All",
"Directory.ReadWrite.All",
"EduAssignments.ReadWriteBasic.All",
"MailboxSettings.Read",
"EduAdministration.Read.All",
"Calls.JoinGroupCallAsGuest.All",
"Sites.Read.All",
"Sites.ReadWrite.All",
"Contacts.ReadWrite",
"Group.ReadWrite.All",
"Sites.Manage.All",
"SecurityEvents.ReadWrite.All",
"Notes.Read.All",
"User.Invite.All",
"EduRoster.ReadWrite.All",
"Files.ReadWrite.All",
"Directory.Read.All",
"User.Read.All",
"EduAssignments.ReadBasic.All",
"EduRoster.ReadBasic.All",
"Files.Read.All",
"Mail.Read",
"Chat.Read.All",
"ChannelMessage.Read.All",
"EduAssignments.Read.All",
"Calendars.ReadWrite",
"identityriskyuser.read.all",
"EduAdministration.ReadWrite.All",
"Mail.Send",
"ChannelMessage.UpdatePolicyViolation.All",
"MailboxSettings.ReadWrite",
"Contacts.Read",
"IdentityRiskEvent.Read.All",
"AuditLog.Read.All",
"Member.Read.Hidden",
"Calls.AccessMedia.All",
"Sites.FullControl.All",
"Reports.Read.All",
"Calls.Initiate.All",
"Notes.ReadWrite.All"
],
"sub": "1111111-98fb-4a47-af7f-d3800dde2f7b",
"tid": "1111111-ccc6-4fd3-bf32-9bfc460f67b1",
"uti": "hxPwbjRRm0y6SI8hxuckAA",
"ver": "1.0",
"xms_tcdt": 1541414851
}
You can see that we get all the necesary permissions.
And this petition works:
https://graph.microsoft.com/v1.0/Users/
or
https://graph.microsoft.com/beta/Users/
but not this one:
https://graph.microsoft.com/beta/Users/<user-id>/Calendars
nor this one:
https://graph.microsoft.com/beta/users/<user-id>/sendMail
they both return 401:
{
"error": {
"code": "UnknownError",
"message": "",
"innerError": {
"request-id": "019ddc83-6528-4f19-95cc-8b99ea53a046",
"date": "2018-11-07T16:03:55"
}
}
}
I think that we had got all the necessary permission, configuration... etc... so why isn't it working? :'(
[UPDATE]
detailed call to get calendars
GET /v1.0/Users/<user-id>/Calendars HTTP/1.1
cache-control: no-cache
Postman-Token: xxxxxxxxxxxxxxxxxxxxxxx
Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
User-Agent: PostmanRuntime/7.3.0
Accept: */*
Host: graph.microsoft.com
accept-encoding: gzip, deflate
Connection: close
Response
HTTP/1.1 401 Unauthorized
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: application/json
request-id: 11111111-aaaa-aaaa-a115-e09bb6f09917
client-request-id: 11111111-aaaa-aaaa-a115-e09bb6f09917
x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"North Europe","Slice":"SliceC","Ring":"3","ScaleUnit":"001","Host":"AGSFE_IN_34","ADSiteName":"NEU"}}
Duration: 377.0084
Strict-Transport-Security: max-age=31536000
Date: Thu, 08 Nov 2018 09:16:03 GMT
Connection: close
c6
{
"error": {
"code": "UnknownError",
"message": "",
"innerError": {
"request-id": "2bb9a7c1-f8a3-4c1f-a115-e09bb6f09917",
"date": "2018-11-08T09:16:04"
}
}
}
0

let me start by first of all noticing that you have posted a client secret on a public forum :) And one that has luxurious permission on your tenant. I hope you have changed the client secret by now.
But to get back to your question - I will have to ask a bit more in detail to get a better understanding of what your actual results were:
According to your JWT printout you are getting a V1 token but using the client credential flow (the field "ver" is set to 1.0). The Microsoft Documentation here Get access without a user explicitly states that you should use a V2 Token to access Microsoft Graph in this scenario. So the first question is: Did you create your Azure App using the V2 Portal: https://apps.dev.microsoft.com/ ? If not then this may be the issue.
A more common issue when manually testing - Have you made sure that the token had not expired from the time you got it from the /token endpoint up to the time you tested your API call?
If none of the above - please post your request to the https://graph.microsoft.com/beta/Users//Calendars endpoint in detail, the devil may be in the details

Related

How do I pass the username/password to authenticate a POST request to a Django rest-framework API from python code?

this is the request I want to emulate in python code, made here with httpie
$ http --auth mucho:pass POST http://3333333.ngrok.io/sms/ msg="love conquers all" to="255123456"
HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 67
Content-Type: application/json
Date: Mon, 30 Dec 2019 20:31:33 GMT
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"id": 70,
"msg": "love conquers all",
"owner": "mucho",
"to": "255123456"
}
I have tried this
from requests import Request,Session
url="http://3333333.ngrok.io/sms/"
data = {
"to": "255123456",
"msg": "love conquers all",
}
s=Session()
req=Request('POST',url,data=data)
preped=req.prepare()
preped.prepare_auth(("mucho","pass"),url)
resp=s.send(preped)
It works, but I am looking for a neater/simpler way possibly using headers. Thanks for any help my way
If you are looking for a way to test your api endpoints, you can use insomnia or postman.
It is easy to set the headers.

Getting code=OrganizationFromTenantGuidNotFound while updating group using Microsoft Graph

I am getting the below exception
"error": {
"code": "OrganizationFromTenantGuidNotFound",
"message": "The tenant for tenant guid '****' does not exist.",
"innerError": {
"request-id": "2acd6af1-99f8-4aab-b71d-cffc60263a05",
"date": "2019-04-20T11:33:04"
}
while updating the group using open extension as shown below: -
POST https://graph.microsoft.com/v1.0/groups/db5f4dbe-40e0-4352-84fb-9a20c131cfaf/extensions HTTP/1.1
Authorization: Bearer ****
Content-Type: text/plain; charset=utf-8
Host: graph.microsoft.com
Content-Length: 111
Expect: 100-continue
Connection: Keep-Alive
{ "#odata.type":"microsoft.graph.openTypeExtension","extensionName":"com.test.nickName","date":"OpenExtension"}
I am using user***#outlook.com id and having active azure subscription. I have given all delegated permission to microsoft graph.
Content type was not specified and it was going as text. Error handling could be improved. After changing content type to "application/json", it is working perfectly fine.
POST https://graph.microsoft.com/v1.0/groups/db5f4dbe-40e0-4352-84fb-9a20c131cfaf/extensions HTTP/1.1 Authorization: Bearer **** Content-Type: application/json; charset=utf-8 Host: graph.microsoft.com Content-Length: 111 Expect: 100-continue Connection: Keep-Alive
{ "#odata.type":"microsoft.graph.openTypeExtension","extensionName":"com.test.nickName","date":"OpenExtension"}

Docusign TSP API

I have applied for the Docusign TSP Program.
We are following these instructions but we are facing some issues.
https://developers.docusign.com/id-tsp-api/guides/tsp-authentication
When we invoke the following route:
POST /oauth/token
POST oauth/token HTTP/1.1
Host: account-d.docusign.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic Y2xpZW50SWQ6Y2xpZW50U2VjcmV0
grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
This should be the response that we are expecting:
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "(access token example removed for document brevity)",
"expires_in": 28800,
"token_type": "Bearer",
"user_api": "https://{server}.docusign.net"
}
Unfortunately we aren't receiving "user_api", instead we are receiving this:
{
"access_token": "ISSUED_ACCESS_TOKEN",
"token_type": "Bearer",
"refresh_token": "ISSUED_REFRESH_TOKEN",
"expires_in": 28800
}
Are you able to help me?

"The access grant authorization_code is not supported" from Azure AD using Oauth 2

I am in the middle of an Authorization Code Grant Flow with Azure AD. Even though the documentation says the grant_type should be authorization_code, I am getting an error message about this property.
POST https://login.windows.net/SOME_AZURE_AD_UUID/oauth2/token?api-version=1.0
Content-Type: application/x-www-form-urlencoded
client_id=SECRET_CLIENT_ID
&client_secret=SECRET_CLIENT_SECRET
&code=SECRET_CODE
&grant_type=authorization_code
&redirect_uri=https://myserver.example.com/login/auth_return
&resource=https://myserver.example.com/
&scope=openid email
(edit: whitespace added for clarity)
The error I am getting back:
HTTP/1.1 400 Bad request
Content-Length: 436
X-Content-Type-Options: nosniff
X-Powered-By: ASP.NET
Request-Id: SOME_REQUEST_ID
X-Ms-Request-Id: SOME_REQUEST_ID
Strict-Transport-Security: max-age=31536000; includeSubDomains
Set-Cookie: x-ms-gateway-slice=slicea; path=/; secure; HttpOnly, stsservicecookie=acs; path=/; secure; HttpOnly
Server: Microsoft-IIS/8.0
Cache-Control: private
Date: Wed, 20 Aug 2014 14:44:08 GMT
Content-Type: application/json; charset=utf-8
{
"correlation_id": "SOME_CORRELATION_ID",
"error": "unsupported_grant_type",
"error_codes": [
70003
],
"error_description": "
ACS70003: The access grant 'authorization_code' is not supported.\r\n
Trace ID: SOME_TRACE_UUID\r\n
Correlation ID: SOME_CORRELATION_ID\r\n
Timestamp: 2014-08-20 14:44:08Z",
"timestamp": "2014-08-20 14:44:08Z",
"trace_id": "SOME_TRACE_UUID"
}
(whitespace added for clarity)
This request does work if I change grant_type to client_credentials (but I have not found a way to use the resulting token for what I need). It also works if I change some URLs to point to Google instead of Azure AD.
Is there a mistake with these requests or does the service genuinely not support the documented grant_type of authorization_code?
This is a bug I believe, and it took me 2-3 days to figure it out. Please do the following to get it working,
1) Remove the "?api-version=1.0" from your URL. I know it sounds strange but trust me their documentation is a mess.
2) Add a "Content-Type": "application/x-www-form-urlencoded" header in your request (hence you'll have to encode the post data values ... for example redirect_url=(encodedURL) etc
3) Remove unnecessary fields from post data REFER ... it should be like
{
'grant_type': "authorization_code",
'resource': "your resource",
'client_id': "your client Id",
'redirect_uri': "your redirect URL",
'client_secret': "your client secret",
'code': "the code u got"
}
I see you have done point 2 so you'll need to do point 1 and you're good to go.
Furthermore, if you want to get access_token quickly(if nothing I said works for you), then pass "client_credentials" in grant_type and you'll get a smaller response with access_token. But if you want the complete response with refresh_token as well, you'll have to do all those steps.
EDIT:
There is one more mistake in their documentation, for Refresh Tokens >>> the URL should be oauth2/token and NOT oauth2/authorize
Hope this helps!
try this
'grant_type':"client_credentials",
'resource': "your resource",
'client_id': "your client Id",
'redirect_uri': "your redirect URL",
'client_secret': "your client secret",

Getting conditionNotMet error on migration of emails > 32kb in size

I've had success migrating small test messages with the Google Email Migration API v2. However, when migrating larger messages, I get an error like:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "conditionNotMet",
"message": "Limit reached.",
"locationType": "header",
"location": "If-Match"
}
],
"code": 412,
"message": "Limit reached."
}
}
I start noticing the error sporadically with messages at 32kb size. At about 40kb in size, the error becomes consistent (no messages succeed). I've confirmed the error occurs whether I'm using google-api-python-client with my non-standard discovery document or the OAuth 2.0 playground. Here's what a successful call and response for a message < 32kb looks like:
POST /upload/email/v2/users/jay#ditoweb.com/mail?uploadType=multipart HTTP/1.1
Host: www.googleapis.com
Content-length: 6114
Content-type: multipart/related; boundary="part_boundary"
Authorization: Bearer <removed>
--part_boundary
Content-Type: application/json; charset=UTF-8
{
'isInbox': 'true',
'isUnread': 'true'
}
--part_boundary
Content-Type: message/rfc822
From: <admin#jay.powerposters.org>
To: <admin#jay.powerposters.org>
Subject: test growing message sizes
Date: Wed, 17 Jul 2013 10:40:48 -0400
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
<last line repeated ~50 times>
--part_boundary--
HTTP/1.1 204 No Content
Content-length: 0
Via: HTTP/1.1 GWA
X-google-cache-control: remote-fetch
Server: HTTP Upload Server Built on Jul 8 2013 15:32:26 (1373322746)
Etag: "S82oyh6kQMvIt9YE14Ogc8RmmsQ/vyGp6PvFo4RvsFtPoIWeCReyIC8"
Date: Wed, 17 Jul 2013 17:35:13 GMT
and here's what a failed message of ~150kb looks like:
POST /upload/email/v2/users/admin#jay.powerposters.org/mail?uploadType=multipart HTTP/1.1
Host: www.googleapis.com
Content-length: 189946
Content-type: multipart/related; boundary="part_boundary"
Authorization: Bearer <removed>
--part_boundary
Content-Type: application/json; charset=UTF-8
{
'isInbox': 'true',
'isUnread': 'true'
}
--part_boundary
Content-Type: message/rfc822
From: <admin#jay.powerposters.org>
To: <admin#jay.powerposters.org>
Subject: test growing message sizes
Date: Wed, 17 Jul 2013 10:40:48 -0400
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
<last line repeated ~1500 times>
--part_boundary--
HTTP/1.1 412 Precondition Failed
Content-length: 240
Via: HTTP/1.1 GWA
X-google-cache-control: remote-fetch
Server: HTTP Upload Server Built on Jul 8 2013 15:32:26 (1373322746)
Date: Wed, 17 Jul 2013 16:57:23 GMT
Content-type: application/json
{
"error": {
"errors": [
{
"domain": "global",
"reason": "conditionNotMet",
"message": "Limit reached.",
"locationType": "header",
"location": "If-Match"
}
],
"code": 412,
"message": "Limit reached."
}
}
Google has fixed the issue on their end. I can now migrate messages of all sizes.

Resources