Not able to update user profile using DocuSign admin API [docusignapi] - c#

I want to update user profile (Federated_status) of user, I am using DocuSign admin APi and generated temporary token from organization admin account - but when I call the Docusing admin api using below it doesn't update it and throws error "unauthorized".
'''try
{
HttpContent PostContent = new StringContent(JsonConvert.SerializeObject(ObjUser), Encoding.UTF8, "application/json");
string reponsebody = string.Empty;
string Url = "https://api-d.docusign.net/managment/v2/organisation/" + OrgID + "users/profiles";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application / json"));
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token));
HttpResponseMessage rep = client.PostAsync(new System.Uri(Url), PostContent).Result;
reponsebody = rep.Content.ReadAsStringAsync().Result;
}
var userProfileResponse = JsonConvert.DeserializeObject<UserProfile>(reponsebody);
return userProfileResponse;
}
'''
I am not sure how to call this admin api to update user profile - "federated status" .
Please help.!

You can do this:
GET /v2/organizations/{organizationId}/users/profile
but the update is:
POST /v2/organizations/{organizationId}/users/profiles
Different endpoint, I know it's confusing.
Make sure you do a POST, not a GET
https://developers.docusign.com/orgadmin-api/reference/Users/Users/updateUser

I suspect that you are not including the proper scopes when obtaining your access token. For requests to DocuSign Admin API, you must include special scopes. I've included some code examples for each type of authentication.
If you're using JWT, your token body will look something like this...
{
"iss": "5c2b8d7e-xxxx-xxxx-xxxx-cda8a50dd73f",
"sub": "464f7988-xxxx-xxxx-xxxx-781ee556ab7a",
"iat": 1523900289,
"exp": 1523903289,
"aud": "account-d.docusign.com",
"scope": "signature organization_read group_read user_read user_write"
}
For Auth Code Grant, your request must include the DocuSign Admin scopes, included in this sample:
https://account-d.docusign.com/oauth/auth?response_type=code&scope=signature%20organization_read%20group_read%20user_read%20user_write&client_id=7c2b8d7e-xxxx-xxxx-xxxx-cda8a50dd73f&state=a39fh23hnf23&redirect_uri=http://example.com/callback/http://example.com/callback/
For Implicit grant, your request will be similar, except a different response type
https://account-d.docusign.com/oauth/auth?response_type=token&scope=signature%20organization_read%20group_read%20user_read%20user_write&client_id=7c2b8d7e-xxxx-xxxx-xxxx-cda8a50dd73f&state=a39fh23hnf23&redirect_uri=http://example.com/callback/
For more information on the various types of scope, see our guide on DocuSign Admin API Auth. Let me know if that helps.

Related

Retrieving a persistent token for Azure user access

I’m working on a project where I need access to a users mailbox (similar to how the MS Flow mailbox connector works), this is fine for when the user is on the site as I can access their mailbox from the graph and the correct permissions request. The problem I have is I need a web job to continually monitor that users mail folder after they’ve given permission. I know that I can use an Application request rather than a delegate request but I doubt my company will sign this off. Is there a way to persistently hold an azure token to access the user information after a user has left the site.. e.g. in a webjob?
Edit
Maybe I've misjudged this, the user authenticates in a web application against an Azure Application for the requested scope
let mailApp : PublicClientApplication = new PublicClientApplication(msalAppConfig);
let mailUser = mailApp.getAllAccounts()[0];
let accessTokenRequest = {
scopes : [ "User.Read", "MailboxSettings.Read", "Mail.ReadWrite", "offline_access" ],
account : mailUser,
}
mailApp.acquireTokenPopup(accessTokenRequest).then(accessTokenResponse => {
.....
}
This returns the correct response as authenticated.
I then want to use this users authentication in a Console App / Web Job, which I try to do with
var app = ConfidentialClientApplicationBuilder.Create(ClientId)
.WithClientSecret(Secret)
.WithAuthority(Authority, true)
.WithTenantId(Tenant)
.Build();
System.Threading.Tasks.Task.Run(async () =>
{
IAccount test = await app.GetAccountAsync(AccountId);
}).Wait();
But the GetAccountAsync allways comes back as null?
#juunas was correct that the tokens are refreshed as needed and to use the AcquireTokenOnBehalfOf function. He should be credited with the answer if possible?
With my code, the idToken returned can be used anywhere else to access the resources. Since my backend WebJob is continuous, I can use the the stored token to access the resource and refresh the token on regular intervals before it expires.
Angalar App:
let mailApp : PublicClientApplication = new PublicClientApplication(msalAppConfig);
let mailUser = mailApp.getAllAccounts()[0];
let accessTokenRequest = {
scopes : [ "User.Read", "MailboxSettings.Read", "Mail.ReadWrite", "offline_access" ],
account : mailUser,
}
mailApp.acquireTokenPopup(accessTokenRequest).then(accessTokenResponse => {
let token : string = accessTokenResponse.idToken;
}
On the backend, either in an API, webJob or Console:
var app = ConfidentialClientApplicationBuilder.Create(ClientId)
.WithClientSecret(Secret)
.WithAuthority(Authority, true)
.WithTenantId(Tenant)
.Build();
var authProvider = new DelegateAuthenticationProvider(async (request) => {
// Use Microsoft.Identity.Client to retrieve token
List<string> scopes = new List<string>() { "Mail.ReadWrite", "MailboxSettings.Read", "offline_access", "User.Read" };
var assertion = new UserAssertion(YourPreviouslyStoredToken);
var result = await app.AcquireTokenOnBehalfOf(scopes, assertion).ExecuteAsync();
request.Headers.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", result.AccessToken);
});
var graphClient = new GraphServiceClient(authProvider);
var users = graphClient.Me.MailFolders.Request().GetAsync().GetAwaiter().GetResult();
In the end I had to abandon using the ConfidentialClientApplicationBuilder, I still use PublicClientApplicationBuilder on the front end to get the users consent but then I handle everything else with the oauth2/v2.0/token rest services which returns and accepts refresh tokens.
That way I can ask the user for mailbox consent using PublicClientApplicationBuilder
Access the user mailbox at any time using oauth2/v2.0/token

Sharepoint Rest API Authentication issues with Access Token Header

I'm trying to implement a C# program to connect to Sharepoint API through modern authentication (Client ID\ Client Secret).
I've registered an APP with Sharepoint overall permissions on Azure Active Directory, in order to generate Client Id and Client Secret.
Next steps should be retrieval of the Access Token from the Microsoft login page, and then construction of all following requests using the bearing token I've generated.
Retrieval of the Access Token just works fine. The problem is when I try to include the token in the authorization header on the following calls.
I always get 401 Unhautorized when building my requests from code. Debugging the response content, what I get is "x-ms-diagnostics: 3000006;reason="Token contains invalid signature"; category"invalid_client".
Instead if I try to replicate the call in Postman I get the following error "{"error_description":"Unsupported security token."}".
I provide my code below. Does anybody knows what is going on?
var b2cAuthUri = "https://login.microsoftonline.com/" + tenantId + "/oauth2/v2.0/token";
var client = new HttpClient();
var dict = new Dictionary<string, string>();
dict.Add("Content-Type", "application/x-www-form-urlencoded");
dict.Add("grant_type", "client_credentials");
dict.Add("client_id", clientId);
dict.Add("client_secret", clientSecret);
dict.Add("scope", scope);
// Execute post method
using (var methodResp = client.PostAsync(b2cAuthUri, new FormUrlEncodedContent(dict)))
{
var callResult = methodResp.Result.Content.ReadAsStringAsync().Result;
if (!string.IsNullOrEmpty(callResult))
{
//I have my Access Token here :)
using (MemoryStream DeSerializememoryStream = new MemoryStream())
{
//initialize DataContractJsonSerializer object and pass custom token class type to it
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(AccessToken));
//user stream writer to write JSON string data to memory stream
StreamWriter writer = new StreamWriter(DeSerializememoryStream);
writer.Write(callResult);
writer.Flush();
DeSerializememoryStream.Position = 0;
//get the Desrialized data in object of type Student
AccessToken SerializedObject = (AccessToken)serializer.ReadObject(DeSerializememoryStream);
var tokenBytes = System.Text.Encoding.UTF8.GetBytes(SerializedObject.access_token);
//64bit serialized token
var tokenBase64 = System.Convert.ToBase64String(tokenBytes);
//Here I try to make a call with the access token as header
var testURI = "https://myorg.sharepoint.com/sites/crmkb/_api/web/lists";
HttpWebRequest testReq = (HttpWebRequest)HttpWebRequest.Create(testURI);
testReq.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + tokenBase64);
testReq.Method = "GET";
//This fails on 401 code
HttpWebResponse response = (HttpWebResponse)testReq.GetResponse();
}
}
}
SharePoint Online has blocked the Azure AD App Client Secret, so if you want to use Azure AD App to authentication with SharePoint Rest API, it's necessary to use Certificate option:
Calling SharePoint Online APIs using Azure AD App-Only permissions and certificate auth
Another option is to use the SharePoint hosted App Id/ Secret registered in "/_layouts/15/appregnew.aspx", this way supported the Client Secret, please check the demo test in Postman:
Accessing SharePoint Data using Postman (SharePoint REST API)

Authorization from C# with auth2 and linkedin

I have a WebApi that I want to authorize my user with his linkedin information (as in create an access token and inject it in to my owin).
So far I have tried to work with Sparkle.Linkedin and this is what I have
public LinkedInLogic() {
// create a configuration object
_config = new LinkedInApiConfiguration(ApiKey, ApiSecret);
// get the APIs client
_api = new LinkedInApi(_config);
}
public Uri GetAuthUrl() {
var scope = AuthorizationScope.ReadBasicProfile;
var state = Guid.NewGuid().ToString();
var redirectUrl = "http://localhost:1510/api/login/RedirectAuth";
return _api.OAuth2.GetAuthorizationUrl(scope, state, redirectUrl);
}
public void GetAccessToken(string code) {
//If I do api.GetAccessToken(code); here I get an access token
var request = System.Net.WebRequest.Create("http://localhost:1510/api/token?grant_type=authorization_code&code=" + code);
request.GetResponse(); // my owin authorization
}
So I first get the Authorization Url -> it opens a popup -> I enter my data and it goes back to a controller which fires up GetAccessToken.
Problem is even if I completely authorize with linkedin I am not sure how to authorize with my own webapi. So I tried to send an http request to my owin token giver but it doesn't like it. There is also doesn't seem to be anyway I can return the access token back to the user so he can use it in his session.
Any ideas?
Not too sure if the sparkle is working anymore since the changes that where made by Linkedin on May 2015

Check User Tokens are valid or not using Twitter Api

I have a Asp.Net application that will post tweets in twitter.
I'm using Twitterizer2 for doing this.
First time when the user uses the application, he will be redirected to twitter for authentication.
And then the user-token will be stored in my application , so that the user will never be asked again to login to twitter.
This is working fine.
Now i want to validate the user-tokens before posting (ie valid token or not) . Is there any way to do this validation?
You can make a call to the Verify Credentials API
Make an authenticated call to
https://api.twitter.com/1/account/verify_credentials.json
It will respond with HTTP 200 OK if the tokens are correct - or 401 if they are not.
MoH's code didn't work for me. Here's what I did:
public bool IsTwitterAccessTokenValid(String access_token, String token_secret)
{
var token = new Twitterizer.OAuthTokens();
token.ConsumerKey = this.TwitterConsumerKey;
token.ConsumerSecret = this.TwitterConsumerSecret;
token.AccessToken = access_token;
token.AccessTokenSecret = token_secret;
var twitterResponse = TwitterAccount.VerifyCredentials(token);
return (twitterResponse.Result == RequestResult.Success);
}
I found out the code for validating tokens in another question.
The Twitterizer Api itself had the Methods to validate the User tokens.
The code is as follows:
Twitterizer.OAuthTokens token = new Twitterizer.OAuthTokens();
token.ConsumerKey = this.AppId;
token.ConsumerSecret = this.AppSecret;
token.AccessToken = userToken;
token.AccessTokenSecret = userSecret;
Twitterizer.TwitterResponse<Twitterizer.TwitterUser> response =
Twitterizer.TwitterAccount.VerifyCredentials(token);
if (String.IsNullOrEmpty(response.ErrorMessage))
{
//This is a valid token
}
else
{
//Invalid token
}

Getting OAuth2 refresh token

I'm trying to use Google's Calendar API to demo out an OAuth2 integration that we'll need to do with another third party. I'm using the DotNetOpenAuth library, and I've been able to get the initial redirect to Google for the Allow / Deny prompt and get the authorization code back.
I now need to get the access token and refresh token, but I only seem to get an access token back, refresh token is null.
This is my controller action method where Google redirects back to after the user Accepts or Denies:
public ActionResult ProcessResponse(string state, string code, string error)
{
var oAuthClient =
new WebServerClient(
new AuthorizationServerDescription
{
TokenEndpoint = new Uri("https://accounts.google.com/o/oauth2/token"),
AuthorizationEndpoint = new Uri("https://accounts.google.com/o/oauth2/auth"),
ProtocolVersion = ProtocolVersion.V20
},
_applicationId,
_secret)
{
AuthorizationTracker = new TokenManager()
};
var authState = oAuthClient.ProcessUserAuthorization();
var accessToken = authState.AccessToken;
var refreshToken = authState.RefreshToken;
return View(new[] { accessToken, refreshToken });
}
Any ideas?
EDIT:
To get the authorization code, I setup the oAuthClient identically to what I did above, and use this method:
oAuthClient.RequestUserAuthorization(new[] { "https://www.googleapis.com/auth/calendar" }, returnUrl);
I had a similar problem, and solved mine by hand-coding the HttpRequest and HttpResponse handling. See code at: https://stackoverflow.com/a/11361759/29156

Categories

Resources