DocuSign C# API - USER_LACKS_MEMBERSHIP error for every token-authenticated request - c#

We had a working application, we went through the go-live process, and everything was running live for several days. Then we started getting SSL errors, and we saw that the nuget package for the DocuSign package had an update (I believe this was all for the 11/13/2019 2019 certificates auto-update), so we updated our code, but now every request returns the USER_LACKS_MEMBERSHIP error for every token-authenticated request.
Things I can confirm are not the issue:
We have authenticated the app via account.docusign.com and the oauth signature impersonation scope, and the testing and live paths are in the API approved Redirect URIs.
We have the correct base path in the configuration (https://na3.docusign.net, as shown on our Apps and Keys page)
The base path did not change after we get the token back (The BaseUri on the Account object matches what we started with)
We are using the correct user for the configuration (The value labeled "API Username" in the Apps and Keys page is entered as "IMPERSONATED_USER_GUID" in appsettings.json and successfully used in creating the token as parameter UserID, which also matches our user account's ID shown in the backend, so we are not confusing it with TARGET_ACCOUNT_ID or CLIENT_ID, and shuffling those around causes errors much earlier at the token generation step).
We only have one user: the administrator of the DocuSign account. Their ID appears in the API configuration labeled as "API Username". The DocuSign administration backend doesn't display a membership tab anywhere for us to correct any possible issues with a user lacking membership. As far as I can tell, Membership is a higher tier account option than what we're paying for, so I'm confused how we could be having problems with a feature we haven't bought.
We get this error for checking envelope status. We get this error for trying to create new envelopes. We get this error for trying to get Account information. The only thing we can do is get an authentication token, but then that token can't be used to make any further authenticated requests.
Is there anything I'm missing that could be causing this other than some database error on DocuSign that I can't correct through the tools available to me? The package update changed the order of which class constructor accepts the ApiClient object, and there's a new AccessToken field on the Configuration class (which I filled out, but doesn't seem to have any effect, since we're still adding the Authorization/Bearer header manually). I'm out of ideas on what to try next.

Are you using the production environment or the demo environment?
I suspect that what's happening is that you are getting them mixed. As the baseUrl should not be demo.docusign.net etc. if you're using production (as indicated by your na3.docusign.net address) but you must ensure that the same account/user from production is also used.
So, the 4 things to check:
userId
accountId.
baseURI
authURI (account-d.docusign.com vs. account.docusign.com)
All of these should match and be for the same account in the same env.

Related

Azure - System Assigned Managed Identities for Function App

I have a function app and need to give it permission to write to blob/table storage. I turned on "System Assigned Managed Identity", and I set the following permissions for it with the scope being the Storage Account I need to access.
Storage Account Contributor
Storage Blob Data Owner
Storage Table Data Contributor
Storage Queue Data Contributor
UPDATE
I remove AZURE_CLIENT_ID, AZURE_CLIENT_SECRET and AZURE_TENANT_ID and then I receive an environment configuration error. I am not running this locally or debugging, I'm triggering it through API Management.
Executed 'Create' (Failed, Duration=1406ms)EnvironmentCredential authentication unavailable. Environment variables are not fully configured. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/environmentcredential/troubleshoot
^ The above link tells me I should add those environment variables back, but it seems like I shouldn't need them according to Peter Bon's answer below
One piece that I find very confusing (because I can't find good documentation on this anywhere) is that I am required by Azure to include three variables
AZURE_CLIENT_ID
AZURE_CLIENT_SECRET
AZURE_TENANT_ID
I am inferring that they are needed to actually allow my function app to access the storage account, which confused me at first because if I just gave it permission explicitly with assigned roles, why do I also need to create something completely outside of my function app to give it permission to do the thing I already gave it permission to do?
My question about this though is "HOW DO I MAKE THIS?" If I need to make an App Registration, what should the callback URL be? What should the API Permissions be? I gave it my best guess and did not get a satisfactory result.
App Registration:
API permissions -> Microsoft.Graph User.Read
Authentication -> https://<mydomain>.onmicrosoft.com/.auth/login/aad/callback
-> ID Tokens
-> Accounts in this organization
Secrets -> Generated new secret to use for AZURE_CLIENT_SECRET
Roles & Admissions -> Cloud application administrator
I then set AZURE_CLIENT_ID to be the app id of this App Registration, AZURE_CLIENT_SECRET to the app registration's secret and AZURE_TENANT_ID to my tenant ID.
Then in my code, I attempt to do the following
var tableUri = new Uri(string.Format("https://{0}.table.core.windows.net/", storageAccountName));
var credential = new DefaultAzureCredential(options);
services.AddScoped(x => new TableServiceClient(tableUri, credential));
And it fails when accessing my table storage with the following error:
Executed 'Create' (Failed, Id=<id>, Duration=2108ms)Server failed to authenticate the request. Please refer to the information in the www-authenticate header.RequestId:<id>Time:2022-10-21T12:15:21.6998519ZStatus: 401 (Server failed to authenticate the request. Please refer to the information in the www-authenticate header.)ErrorCode: InvalidAuthenticationInfoContent:{"odata.error":{"code":"InvalidAuthenticationInfo","message":{"lang":"en-US","value":"Server failed to authenticate the request. Please refer to the information in the www-authenticate header.\nRequestId:<id>\nTime:2022-10-21T12:15:21.6998519Z"}}}Headers:Server: Microsoft-HTTPAPI/2.0x-ms-request-id: <id>x-ms-error-code: REDACTEDWWW-Authenticate: Bearer authorization_uri=https://login.microsoftonline.com/<tenant_id>/oauth2/authorize resource_id=https://storage.azure.comDate: Fri, 21 Oct 2022 12:15:21 GMTContent-Length: 279Content-Type: application/json
and if I update the Authentication redirect to
https://storage.azure.com
then I get the following error:
Executed 'Create' (Failed, Id=<id>, Duration=2349ms)This request is not authorized to perform this operation using this permission.RequestId:<request>Time:2022-10-21T13:14:29.0955823ZStatus: 403 (Forbidden)ErrorCode: AuthorizationPermissionMismatchContent:{"odata.error":{"code":"AuthorizationPermissionMismatch","message":{"lang":"en-US","value":"This request is not authorized to perform this operation using this permission.\nRequestId:<id>\nTime:2022-10-21T13:14:29.0955823Z"}}}Headers:Cache-Control: no-cacheTransfer-Encoding: chunkedServer: Windows-Azure-Table/1.0,Microsoft-HTTPAPI/2.0x-ms-request-id: <id>x-ms-client-request-id: <id>x-ms-version: REDACTEDX-Content-Type-Options: REDACTEDDate: Fri, 21 Oct 2022 13:14:28 GMTContent-Type: application/json; odata=minimalmetadata; streaming=true; charset=utf-8
I am honestly pretty confused at this point, can someone please help me understand how to successfully set up system assigned managed identities?
UPDATE WITH ANSWER
figured it out w/ suggestion from Peter.. so, I'm not a C# developer, but have a programming background & am doing devops for this project, another group is coding the application. I didn't realize that they had specifically used new EnvironmentCredential(); in their code, since they emphasized always needing to use DefaultAzureCredential but the EnvironmentCredential forces the setting of AZURE_CLIENT_ID. This also explains our issue w/ using DefaultAzureCredential because it goes through the list like you linked in the answer, so it sees AZURE_CLIENT_ID is set, and doesn't bother going for MI even though MI has the right permissions.
When using a managed identity you should not provide these env variables. It would also defeat the purpose of not having to store a secret. They are not required in that scenario. It is just one of the many ways DefaultAzureCredential tries to get valid credentials. See this section. If you do not provide them, it will fall back trying to use a managed identity.

AAD client-credentials flow request scope for web api

I got a console app that needs to support two flows, authenticating against AAD to talk to a web api:
for regular usage by humans, it needs to support interactive login
for usage by a CI/CD pipeline it needs to support client-credentials.
The interactive flow works perfectly, but the client-credentials flow is giving me problems with the requested scope.
I'm using the latest Microsoft.Identity* nuget packages.
When I construct the scope for the webapi like I do for the interactive flow, I get an error message telling me that for client-credentials flows I need to append ./default. Okay, fair enough, I also found documentation for this, so I append ./default. But when I do that, I get another error message telling me
The resource principal named api:///access_as_user was not found in the tenant named .
There are two problems with this error message:
the resource principal quoted definitely exists - also, I couldn't login interactively if it didn't, but as mentioned, interactive login works just fine
it says api://<webApiAppId>/access_as_user, not api://<webApiAppId>/access_as_user/.default, despite my appending that
My next though was: well, maybe the problem is that the app registration used for the client-credentials flow doesn't have permissions on the web-api. But it does.
So now I've run out of ideas. Hopefully, someone here can help.
To make everything a bit clearer, let me list the app regs involved:
A. Web Api
Was setup via the VS Wizard/dotnet-msidentity tool
has a few App Roles defined
exposes a single API api://<itsownAppId>/access_as_user
B. Interactive Login
manually created
redirect URI for localhost
API Permissions: added WebApi | access_as_user as delegated
C. Non-interactive login/Service Principal
setup manually
is used also for other things by the CI/CD pipeline
has a ClientSecret defined
API Permissions: added WebApi | access_as_user with 2 of the app roles defined for A
has other API Permissions that have nothing to do with this here (for Graph)
granted admin consent for all permissions
The code I use to authenticate is (for the confidential flow):
ConfidentialClientApplicationBuilder.Create(_configuration.ApplicationId)
.WithTenantId(_configuration.Directory)
.WithLogging(Log, LogLevel.Error)
.WithClientSecret(_configuration.ClientSecret)
.Build()
.AcquireTokenForClient(_configuration.Scopes)
.ExecuteAsync();
where the values of _configuration are:
ApplicationId: the appId from app registration C
Directory: the name of my AAD tenant
ClientSecret: the secret from app registration C
Scopes: array of openid, profile and api://<appIdOfWebApiFromC>/access_as_user/.default
So, it turns out that the documentation for appending ./default is not quite clear enough:.You are not meant to append it to the scope, just to the "resource id". And with resource id they mean the "api://" parts without the name of the permission.
So where you normally request api://<webApiAppId>/access_as_user, for the client-credentials flow you have to request api://<webApiAppId>/.default

My AzureAD - registered application doesn't have the rights to do anything ...?

I'm writing a c# program right now that tries to authenticate with Azure to make a generic http request. I finally got the code working and I wanted to test the features but for every request I make I get the following error code in response:
{"error":{"code": "AuthorizationFailed", "message":"The client "(id of the app I registered in AzureAD)" with object id "(same value as before)" does not have authorization to perform action 'Microsoft.Authorization/roleAssignments/read' over scope '/subscriptions/(mysubscriptionid)'."}}.
The thing is ... The account I use to set everything up is a global admin. I checked every permission box in AzureAD I could find...
(that's 8 Application Permissions and 9 Delegated permissions in the Windows Azure Active Directory API and 1 delegated Permission in the Windows Azure Service Management API, though I don't know why there aren't more possible permissions for Azure Service Management)
the relevant code is rather basic but it works so I don't feel like I need post it, I'll just say that I obtain the Token using Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenAsync() with
authorityUri = "https://login.windows.net/(mytenantid)",
string resourceUri = "https://management.azure.com/";
AuthenticationContext authContext = new AuthenticationContext(authorityUri);
var res = authContext.AcquireTokenAsync(resourceUri, new
ClientCredential(clientId,clientSecret));
return res.Result;
and make the Request to
https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Authorization/roleAssignments?api-version=2016-03-01&$filter=atScope()
(as an example, this one is supposed to call the roles).
Tried several different types of GET Requests to different URIs, all give similar errors.
I'm thinking it might not be an issue with the code but a setting in the AzurePortal but everything I found there seems set up right (or rather "universal access").
According to your description, you forget to grant your service principal. You could add it on Azure Portal. You could grant Contributor or Owner role to it.
Please refer to this link:Assign application to role.

Custom MFA ADFS extension does not work with e-mail claim

I have built an MFA extension for ADFS using this guide: https://blogs.msdn.microsoft.com/jenfieldmsft/2014/03/24/build-your-own-external-authentication-provider-for-ad-fs-in-windows-server-2012-r2-walk-through-part-1/
I am trying get the incoming claim in the IAuthenticationAdapter.BeginAuthentication(Claim claim, ...) to have the e-mail of the user that is authenticating. Based on the guide, i should be able to specify in my metadata the IdentityClaims to return "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" and then i should get the e-mail.
However, my code is never hit.
Instead, i get the following error in the Event Viewer logs:
System.IO.InvalidDataException: The identity information provided does not contain a Windows account name.
at Microsoft.IdentityServer.Web.Authentication.External.ExternalAuthenticationHandler.ProcessContext(ProtocolContext context, IAuthenticationContext authContext, IAccountStoreUserData userData)
at Microsoft.IdentityServer.Web.Authentication.External.ExternalAuthenticationHandler.Process(ProtocolContext context)
at Microsoft.IdentityServer.Web.Authentication.AuthenticationOptionsHandler.Process(ProtocolContext context)
at Microsoft.IdentityServer.Web.PassiveProtocolListener.OnGetContext(WrappedHttpListenerContext context)
I tried specifying the relying party trusts to pass on the LDAP parameters but i am unable to access those in my code.
Any suggestions?
Background
We ran into this question when trying to debug this exact issue, ourselves. We were experimenting with IAuthenticationAdapterMetadata.IdentityClaims. When our adapter requested emailaddress as our input claim, ADFS threw the above exception immediately before calling BeginAuthentication.
The main issue was that our Claims Provider (Active Directory, in this case) was not configured to provide the user's email address. We discovered this with help from Microsoft's (free) Claims X-Ray service, which I highly recommend for those debugging ADFS claims issues.
Secondarily, ADFS was giving a misleading error. ADFS does not actually seem to validate the Claim value passed to BeginAuthentication. Once we resolved the main issue, there were no restrictions on the user's email address, so long as it was defined.
Solution
Note: if you have multiple Claims Provider Trusts, you may need to do this with each of them.
Navigate to the AD FS Management app on the relevant machine.
Select Claims Provider Trusts.
Right click the provider you want to "fix" and select Edit Claim rules...
Select Add Rule... and then select Send LDAP Attributes as Claims.
I'm assuming you should select the provider you're working on as the Attribute store for this rule. You may need to experiment if you can't.
Map LDAP attribute E-Mail-Addresses to claim type E-Mail Address.
Save the new rule.
Additional note: Only the first value in the E-Mail-Addresses array will be sent to BeginAuthentication. This seems to be a quirk of the interface, not a quirk of this solution.

Azure AD Graph call for User creation failing with some obscure error

I have been told to raise a question about Azure AD Graph Api here instead of raising it as an issue for the corresponding GitHub sample repository, I hope Azure Graph API team monitors SO and can help us with this github sample issue
Some extra context for the problem:
We are using Microsoft.Azure.ActiveDirectory.GraphClient nuget to create and manage users in our Azure AD test tenant. Following this sample application
we can create and update users in Azure AD via Graph API. That was fine until some moment which happened about 2-3 days ago (not sure about the exact moment, we discovered the problem on Tuesday morning AU time. Last successful run was on Friday last week). It was 100% working code and to confirm that it's not our code - I ran through sample application again - it's broken now too. I've tested it with the latest GraphClient v2.1.0 and original one from sample app which is - v2.0.6
To simplify testing of the problem I've made a LINQ based sample with some secrets redacted ( you need to follow console app sample guide to put in your values if you want to run it, instead of original sample app)
Also here is the Fiddle captures (redacted) of
Authentication request-response (client-request-id: 88b2bbbd-94cd-498d-a147-caad05e16eb7)
User Creation failing Attempt
Few things to note in the fiddler captures - Azure AD Graph API doesn't return refresh token along with access token:
{"expires_in":"3599","token_type":"Bearer","scope":"UserProfile.Read",
"expires_on":"1441183928","not_before":"1441180028","resource":"https://graph.windows.net",
"access_token":"TOKEN WAS HERE"}
I can see the issue with the scope string here, but we are not setting any explict scope in GraphClient when calling for token as per Sample app ( and this code was fine before, as I mentioned early)
User creation response is clear in terms of what happens and why it happens
{"odata.error":
{"code":"Authorization_RequestDenied","message":
{"lang":"en","value":"Insufficient privileges to complete the operation."}
}
}
But it's not clear how to ask for extra permission scopes through any of these AuthenticationContext.AcquireToken Method overloads
Also it's strange that the very same code was fully functional before and is broken now, after some mysterious change?
So I have few questions:
How to add extra scope permissions in GraphClient library to get Graph API token with User Modification enabled. This is probably a band aid fix of the problem.
It looks like Azure AD tries to manage permissions for client apps in the portal. But there is no extra permissions for Native Client type of application. How can I explicitly update app permissions so the existing code can work again. Is it possible at all ?
Can anyone recommend other libraries to interact with GraphAPI, which allow the consumer to explicitly specify scope for the requested token ?
================Update================
Yes, I saw that consent flow documentation. Chasing the issue I've created new Azure AD tenant, added brand new application and added all possible rights, including all available application and delegation ones:
now it looks like this. I also
I can get a token with long list of scopes, e.g.
Directory.AccessAsUser.All
Directory.Read
Directory.Write
User.Read
User.ReadWrite
User.Read.All
User.ReadBasic.All
User.ReadWrite.All
user_impersonation
UserProfile.Read
--cut unrelated scopes--
But it still gives me 403 :
{"odata.error":
{"code":"Authorization_RequestDenied","message":
{"lang":"en","value":"Insufficient privileges to complete the operation."}
}
}
One thing worth to note - in the scope list there is no Directory.ReadWrite.All
But here docs says :
Directory.ReadWrite.All : Read and write directory data
================Update================
PS: Some technical request info for Azure AD engineers:
Authentication request-response has client-request-id: 88b2bbbd-94cd-498d-a147-caad05e16eb7.
Failed Graph call has client-request-id: 882f3918-0ddd-40fe-a558-866997e32b46 in response only
The issue here is that you have not properly configured your application to request the correct permissions to the Graph API.
To do this, you must go into the Azure Management Portal and configure your 'permissions to other applications' to include the scopes your app needs to be able to read/write to the directory.
We have some documentation here which should help you:
https://msdn.microsoft.com/en-us/library/azure/dn132599.aspx (Describes the consent flow)
https://msdn.microsoft.com/Library/Azure/Ad/Graph/api/graph-api-permission-scopes (describes the specific permissions that the graph API exposes that your application will need to request)
I hope this helps!

Categories