Docusign TSP API - docusignapi

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?

Related

Getting the API Key from ServiceStack request

Have a simple get Customer api that's returning list of customers fine.
Setting up for service to service authentication, if I make this [Authenticated] and try to implement using ApiKeyAuthProvider, the req.GetApiKey returns null and I get an error;
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 POST https://localhost:44347/api/customers application/json 0
Microsoft.AspNetCore.Hosting.Internal.WebHost:2019-07-01 16:50:34,004 [16] INFO Microsoft.AspNetCore.Hosting.Internal.WebHost - Request starting HTTP/1.1 POST https://localhost:44347/api/customers application/json 0
The thread 0x42cc has exited with code 0 (0x0).
The thread 0x302c has exited with code 0 (0x0).
ServiceStack.ServiceStackHost:2019-07-01 17:01:14,601 [16] ERROR ServiceStack.ServiceStackHost - ServiceBase<TRequest>::Service Exception
System.ArgumentOutOfRangeException: Length cannot be less than zero.
Parameter name: length
at System.String.Substring(Int32 startIndex, Int32 length)
at ServiceStack.Host.HttpRequestAuthentication.GetBasicAuth(IRequest httpReq) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\HttpRequestAuthentication.cs:line 45
at ServiceStack.Host.HttpRequestAuthentication.GetBasicAuthUserAndPassword(IRequest httpReq) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\HttpRequestAuthentication.cs:line 50
at ServiceStack.Auth.ApiKeyAuthProvider.PreAuthenticate(IRequest req, IResponse res) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Auth\ApiKeyAuthProvider.cs:line 232
at ServiceStack.AuthenticateAttribute.PreAuthenticate(IRequest req, IEnumerable`1 authProviders) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\AuthenticateAttribute.cs:line 96
at ServiceStack.AuthenticateAttribute.ExecuteAsync(IRequest req, IResponse res, Object requestDto) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\AuthenticateAttribute.cs:line 74
at ServiceStack.Host.ServiceRunner`1.ExecuteAsync(IRequest req, Object instance, TRequest requestDto) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\ServiceRunner.cs:line 127
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 640574.8754ms 400 application/json; charset=utf-8
Microsoft.AspNetCore.Hosting.Internal.WebHost:2019-07-01 17:01:14,607 [16] INFO Microsoft.AspNetCore.Hosting.Internal.WebHost - Request finished in 640574.8754ms 400 application/json; charset=utf-8
Clearly I have missed something obvious...any pointers appreciated.
// Register ORMLite connection
container.Register<IDbConnectionFactory>(dbFactory);
//Tell ServiceStack you want to persist User Auth Info in SQL Server
container.Register<IAuthRepository>(c => new OrmLiteAuthRepository(dbFactory));
// See https://docs.servicestack.net/api-key-authprovider
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new ApiKeyAuthProvider(AppSettings) {
SessionCacheDuration = TimeSpan.FromMinutes(10),
AllowInHttpParams = true, // Whether to allow API Keys in 'apikey' QueryString or FormData (e.g. `?apikey={APIKEY}`)
RequireSecureConnection = true,
},
}
) {
IncludeRegistrationService = true,
});
GlobalRequestFilters.Add((req, res, dto) =>
{
LastApiKey = req.GetApiKey();
});
Request
POST https://localhost:44347/api/customers HTTP/1.1
Host: localhost:44347
Connection: keep-alive
Content-Length: 2
Accept: application/json
Origin: https://localhost:44347
Authorization: yDOr26HsxyhpuRB3qbG07qfCmDhqutnA-yDOr26HsxyhpuRB3qbG07qfCmDhqutnA-yDOr26HsxyhpuRB3qbG07qfCmDhqutnA
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Content-Type: application/json
Referer: https://localhost:44347/swagger-ui/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,en-US;q=0.8
{}
Response
HTTP/1.1 400 ArgumentOutOfRangeException
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Vary: Accept,Origin
Server: Microsoft-IIS/10.0
X-Powered-By: ServiceStack/5.50 NetCore/Windows
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS
Access-Control-Allow-Headers: Content-Type
X-Startup-Errors: 1
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: Content-Disposition
X-SourceFiles: =?UTF-8?B?QzpcUmVwb3NcTUJXZWJccnZhcGlcUnZXZWJcUnZBcGlcYXBpXGN1c3RvbWVycw==?=
X-Powered-By: ASP.NET
Date: Wed, 03 Jul 2019 08:07:40 GMT
13e
{"responseStatus":{"errorCode":"ArgumentOutOfRangeException","message":"Length cannot be less than zero.\r\nParameter name: length","errors":[{"errorCode":"ArgumentOutOfRangeException","fieldName":"length","message":"Length cannot be less than zero.\r\n"}]},"responseCreatedUtcDateTime":"2019-07-03T08:07:40.7955827Z"}
0
Your client is sending an invalid Authorization Bearer Token, it needs to have the Authroization Bearer Token format:
Authorization: Bearer {Token}
If you're sending an Authenticated API Key or JWT Request via Open API it needs to have the Bearer prefix as per the Open API docs:
OK I had manually created a User and APIKey in the underlying tables and had used a UserAuthId 'SomeAuthId' i.e. letter in them, and the ORM repository code is expecting these to be integers. Its cool that I can see the code in github and debug this myself - thanks for the comment as it got me thinking and looking into my Auth setup.

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"}

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

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

Create AD user and add to group at the same time?

I know how to create an AD B2C user, as well as add them to a group via the graph API. I'm doing this in my Azure Function. What I'm wondering is, is it possible to create the user and add them to the group at the same time? If not, then I suppose I'll have to handle the potential case of a user being created but failing to be added to a group. How likely is this sort of scenario? I'm trying to make sure I cover all my bases for all failure conditions, so any input would be appreciated. Thanks.
It seems like you want to use Batch Processing for these kinds of requests.
Here is the sample request they post in the article:
The following example shows a batch request that contains five items:
A change set that creates a user, testuser#contoso.onmicrosoft.com (POST). This operation includes the Prefer: response-no-content header to suppress the newly created user being returned.
A change set that updates the Department and Job Title properties of the new user (PATCH), and sets its manager navigation property (PUT).
A query for the manager of the new user (GET).
A change set that deletes the new user (DELETE).
A query for the user (GET). This operation will fail because the user was deleted in the previous step.
POST https://graph.windows.net/contoso.onmicrosoft.com/$batch?api-version=1.5 HTTP/1.1
Authorization: Bearer ey … jQA
Content-Type: multipart/mixed; boundary=batch_36522ad7-fc75-4b56-8c71-56071383e77b
Host: graph.windows.net
Content-Length: 2961
--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: multipart/mixed; boundary=changeset_77162fcd-b8da-41ac-a9f8-9357efbbd620
Content-Length: 631
--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd620
Content-Type: application/http
Content-Transfer-Encoding: binary
POST /contoso.onmicrosoft.com/users?api-version=1.5 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 256
Prefer: return-no-content
Host: graph.windows.net
{
"accountEnabled": true,
"displayName": "Test User",
"mailNickname": "testuser",
"passwordProfile": { "password" : "Test1234", "forceChangePasswordNextLogin": false },
"userPrincipalName": "testuser#contoso.onmicrosoft.com"
}
--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd620----batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: multipart/mixed; boundary=changeset_4b2cbfb7-011d-4edb-8bbf-e044f9830aaf
Content-Length: 909
--changeset_4b2cbfb7-011d-4edb-8bbf-e044f9830aaf
Content-Type: application/http
Content-Transfer-Encoding: binary
PATCH /contoso.onmicrosoft.com/users/testuser#contoso.onmicrosoft.com?api-version=1.5 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 72
Host: graph.windows.net
{
"department": "Engineering",
"jobTitle": "Test Engineer"
}
--changeset_4b2cbfb7-011d-4edb-8bbf-e044f9830aaf
Content-Type: application/http
Content-Transfer-Encoding: binary
PUT /contoso.onmicrosoft.com/users/testuser#contoso.onmicrosoft.com/$links/manager?api-version=1.5 HTTP/1.1
Content-Type: application/json
Accept: application/json
Content-Length: 112
Host: graph.windows.net
{
"url":"https://graph.windows.net/contoso.onmicrosoft.com/users/a71e4d1c-ce99-40dc-8d4b-390eac63e039"
}
--changeset_4b2cbfb7-011d-4edb-8bbf-e044f9830aaf----batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: application/http
Content-Transfer-Encoding:binary
GET /contoso.onmicrosoft.com/users/testuser#contoso.onmicrosoft.com/$links/manager?api-version=1.5 HTTP/1.1
Accept: application/json
Host: graph.windows.net
--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: multipart/mixed; boundary=changeset_9a0b5878-0f4a-4f57-91c5-9792cdd5ef20
Content-Length: 331
--changeset_9a0b5878-0f4a-4f57-91c5-9792cdd5ef20
Content-Type: application/http
Content-Transfer-Encoding: binary
DELETE /contoso.onmicrosoft.com/users/testuser#contoso.onmicrosoft.com?api-version=1.5 HTTP/1.1
Accept: application/json
Host: graph.windows.net
--changeset_9a0b5878-0f4a-4f57-91c5-9792cdd5ef20----batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: application/http
Content-Transfer-Encoding:binary
GET /contoso.onmicrosoft.com/users/testuser#contoso.onmicrosoft.com?api-version=1.5 HTTP/1.1
Accept: application/json
Host: graph.windows.net
--batch_36522ad7-fc75-4b56-8c71-56071383e77b--

TXT post to DocuSign always gives INVALID_MULTI_PART_REQUEST Boundary terminator not found error

I'm new to this and probably doing something very stupid, but if I carry on like this, I'll be bald!
As a test, I am just trying to send a TXT document for signing to DocuSign via a HTTP Post. I have followed the examples they give (I believe) but what ever I try, I get the same error.
Error:
"INVALID_MULTI_PART_REQUEST",
"message": "An error was found while parsing the multipart request. Boundary terminator '--AAAAA--' was not found in the request.
Ultimately I want to send base64 encoded PDFs but if I cannot even get TXTs to work...
I am using an XML scripting language specific to our in-house application to make the HTTP request, and the process has a diagnostic mode which can dump the request elements out to file to help sort issues: These TXT files are next and I have removed any sensitive data:
REQUESTHEADERS.TXT:
Content-Type: multipart/form-data; boundary=AAAAA
Content-Length: 565
X-DocuSign-Authentication: <DocuSignCredentials> <Username>myemail#myemail.com</Username><Password>mypassword</Password> <IntegratorKey>mykey</IntegratorKey></DocuSignCredentials>
Host: demo.docusign.net
Accept: application/json; charset=UTF-8
Accept-Encoding: identity
User-Agent: Mozilla/3.0 (compatible; Indy Library)
REQUESTDATA.TXT
Content-Type: application/json; charset=UTF-8
Content-Transfer-Encoding: 8bit
Content-Disposition: form-data
{
"status":"created",
"emailSubject":"Test",
"emailBlurb":"This is a test",
"documents":[
{
"name":"test1.txt",
"documentId":"1",
"order":"1"
}
],
"recipients":{
"signers":[
{
"email":"myemail#myemail.com",
"name":"Fred Blogs",
"recipientId":"1"
}
]
}
}
--AAAAA
Content-Type: text/plain; charset=UTF-8
Content-Disposition: file; filename="test1.txt";documentid=1
Please sign this test document
--AAAAA--
Please, if any one can tell me what is wrong I would be very grateful indeed!
It's the formatting of the call, please take note on where I have line breaks and where I do not.
Request
--AAAAA
Content-Type: application/json; charset=UTF-8
Content-Transfer-Encoding: 8bit
Content-Disposition: form-data
{
"status":"created",
"emailSubject":"Test",
"emailBlurb":"This is a test",
"documents":[
{
"name":"test1.txt",
"documentId":"1",
"order":"1"
}
],
"recipients":{
"signers":[
{
"email":"myemail#myemail.com",
"name":"Fred Blogs",
"recipientId":"1"
}
]
}
}
--AAAAA
Content-Type: text/plain; charset=UTF-8
Content-Disposition: file; filename="test1.txt";documentid=1
Please sign this test document
--AAAAA--
Response
{
"envelopeId": "{envelopeId}",
"uri": "/envelopes/{envelopeId}",
"statusDateTime": "2015-02-27T18:53:39.5700000Z",
"status": "created"
}

Resources