C# MS-CRM 2013 online Plugin To Publish Event On Facebook Page - dynamics-crm-2011

My solution may not be technically possible. Yet I would like your viewpoint
We have to create a workflow/plugin MS-CRM 2013 which will publish events from CRM to a particular facebook page.
A separate application is not possible.
The problem is, to publish I need Page Access Token.
To get Page Access Token I need User Access Token.
To get User Access Token I need to follow the redirect_uri path where I will get the code in URL string but MS-CRM 2013 as you might be aware does not allow "code" as url string, it will refuse to redirect itself to my callback page, that is my problem.
I am open to suggestions I have used Facebook SDK and simple webrequest.this gives me the App Access Token
dynamic result = obj.Get("oauth/access_token", new
{
client_id = this.fbAppID,
client_secret = this.fbAppSecret,
grant_type = "client_credentials",
scope = "publish_actions,manage_pages,create_event,read_stream,publish_stream,email,read_friendlists,read_insights,read_requests,manage_friendlists,user_about_me,user_activities,user_birthday,user_groups,friends_groups"
});
Now How do I get the user access token from inside MS-CRM 2013 online.
If somebody has done it please do let me know, if you need more clarification I will be happy to provide more code etc.

You need to separate your logic:
Create an HTML/JavaScript WebResource combo that allows a user to link their CRM SystemUser record to Facebook. Build code similar to that below - it'll need additional supporting code to check if the user is already connected to Facebook, etc.
FB.login(function (response) {
if (response.authResponse) {
// user sucessfully logged in
var accessToken = response.authResponse.accessToken;
//TODO: Add logic to save accessToken to CRM SystemUser record.
}
}, { scope: 'email,publish_stream,email,rsvp_event,read_stream,user_likes,user_birthday' });
In your plugin retrieve the FB Access Token, saved in step 1, from the CRM SystemUser record, and use that to instantiate your Facebook connection object:
var obj = new FacebookClient(accessToken);
This is a bunch of work to do to get the access token. And none of the guides are going to clearly explain mixing pure HTML/JS for token retrieval but making the calls from C#, since this is a fairly unusual requirement.

Related

Setting up an Application with Azure for use with Graph API outlook calendars

I'm aware that Graph API has a nice nuget package and I am confident on the code side of things, but my understanding is that I need to have the application set up in Azure and while there is a lot of documentation about this in general, I find it quite dense and I'm not confident I have the specifics down for how I need to set this portion up.
What I need my application to do is access an outlook calendar of a specific user that I own, read, search, add, delete and update calendar items. The integration assistant seems to suggest I need to configure a URI redirect and configure api permission. The default persmission is User.Read on graph API and if I try to add a permission, office 365 management seems like it might be the one I need except it specifically says just retrieving user information and nothing mentions outlook anywhere.
I need to know more or less the minimum steps in setting up the application in Azure to write a C# application that can make changes to outlook for a user.
need my application to do is access an outlook calendar of a specific user
Does it mean you need your app to have the abiltity to modify the callendar of any user you owned? If not, then it means you need your application to provide a sign in module and let users sign in, then the users can get authentication to call graph api and manage their own calendar, since this scenario, users give the delegate api permission, so they can't manage other users' calendar, so I don't think this is what you want.
If so, then you should use client credential flow to generate access token to call graph api. I think you know that when you want to call graph api, you have to get an access token which has correct permission first.
Ok, then let's come to the api permission, when you go to api document of the Calendar. You will see permissions like screenshot below:
Application permission type is suitable for client credential flow. And after viewing all the apis, you will find that they all need Calendars.ReadWrite except those not supporting Application type.
Then let's go to azure portal and reach Azure Active Directory. You need to create an Azure ad application and give the app Calendars.ReadWrite permission, then give the Admin consent.
Then you also need to create a client secret, pls go to Certificates & Secrets and add a new client secret, don't forget to copy the secret after you create it.
Now you've done all the steps. No need to set a redirect url, because you don't need to let the user to sign in your application. Let's see client credential flow document, it only require client_id, client_secret to generate access token.
Or in the code, you may use SDK like this :
using Azure.Identity;
using Microsoft.Graph;
public async Task<IActionResult> Index()
{
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "your_tenant_name.onmicrosoft.com";
var clientId = "azure_ad_app_id";
var clientSecret = "client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var calendar = new Calendar{ Name = "Volunteer" };
var events = await graphClient.Users["user_id_which_is_needed_to_list_calendar_events"].Events.Request()
.Header("Prefer","outlook.timezone=\"Pacific Standard Time\"")
.Select("subject,body,bodyPreview,organizer,attendees,start,end,location")
.GetAsync();
return View();
}

Docusign - Auto Sending Email on form submit

Im working a Laravel Project where we need to get the form details and send them to users to get sign through docusign. I refereed the PHP SDK but not sure where to get the JWT TOKEN, since the normal authentication is asking for docusign credentials each time when submit, we planned to use JWT authentication, please correct me if their are any options apart for this. Reviewed the Rest API, they mentioning the JWT will expire in 1hr, so should we manually generate JWT every 1hr. Please let me know wat is the best approach for handling this.
with JWT, you only need consent once in a lifetime and then you can generate tokens whenever you need.
You can get started by cloning this repo and following instructions to see how DocuSign APIs work with JWT.
The relevant code for getting a JWT token using PHP is this:
public function login() {
self::$access_token = $this->configureJwtAuthorizationFlowByKey();
self::$expiresInTimestamp = time() + self::$expires_in;
if(is_null(self::$account)) {
self::$account = self::$apiClient->getUserInfo(self::$access_token->getAccessToken());
}
$redirectUrl = false;
if (isset($_SESSION['eg'])) {
$redirectUrl = $_SESSION['eg'];
}
self::authCallback($redirectUrl);
}
To gain consent, open a browser (only once needed) with this URL - https://account-d.docusign.com/oauth/auth?response_type=code&scope=signature%20impersonation&client_id=<YOUR_INT_KEY>&redirect_uri=<YOUR_REDIRECT_URI>

Asking for user info anonymously Microsoft Graph

In an old application some people in my company were able to get info from Microsoft Graph without signing users in. I've tried to replicate this but I get unauthorized when trying to fetch users. I think the graph might have changed, or I'm doing something wrong in Azure when I register my app.
So in the Azure portal i have registered an application (web app), and granted it permissions to Azure ad and Microsoft graph to read all users full profiles.
Then I do a request
var client = new RestClient(string.Format("https://login.microsoftonline.com/{0}/oauth2/token", _tenant));
var request = new RestRequest();
request.Method = Method.POST;
request.AddParameter("tenant", _tenant);
request.AddParameter("client_id", _clientId);
request.AddParameter("client_secret", _secret);
request.AddParameter("grant_type", "client_credentials");
request.AddParameter("resource", "https://graph.microsoft.com");
request.AddParameter("scope", "Directory.Read.All");
I added the last row (scope) while testing. I still got a token without this but the result is same with or without it.
After I get a token I save it and do this request:
var testClient = new RestClient(string.Format("https://graph.microsoft.com/v1.0/users/{0}", "test#test.onmicrosoft.com")); //I use a real user here in my code ofc.
testRequest = new RestRequest();
testRequest.Method = Method.GET;
testRequest.AddParameter("Authorization", _token.Token);
var testResponse = testClient.Execute(testRequest);
However now I get an error saying unauthorized, Bearer access token is empty.
The errors point me to signing users in and doing the request, however I do not want to sign a user in. As far as i know this was possible before. Have Microsoft changed it to not allow anonymous requests?
If so, is it possible to not redirecting the user to a consent-page? The users are already signed in via Owin. However users may have different access and i want this app to be able to access everything from the azure ad, regardless of wich user is logged in. How is the correct way of doing this nowadays?
Or am I just missing something obvious? The app has been given access to azure and microsoft graph and an admin has granted permissions for the app.
Edit: just to clarify, i tried both "Authorization", "bearer " + _token.Token, and just _token.Token as in the snippet.
Yes, it's still possible to make requests to Graph without a user present using application permissions. You will need to have the tenant admin consent and approve your application.
Edit / answer: Adding the 'Authorization' as a header instead of a parameter did the trick. It works both with 'bearer token' and just 'token'

.NET Gmail OAuth2 for multiple users

We are building a solution that will need to access our customers Gmail accounts to read/send mail. On account signup, we'd have a pop-up for our customer to do Gmail auth page and then a backend process to periodically read their emails.
The documentation doesn't seem to cover this use case. For example https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth says that client tokens should be stored in client_secrets.json - what if we have 1000s of clients, what then?
Service accounts are for non-user info, but rather application data. Also, if I use the GoogleWebAuthorizationBroker and the user has deleted access or the tokens have expired, I don't want my backend server app to pop open a web brower, as this seems to do.
I would imagine I could use IMAP/SMTP accomplish this, but I don't think it's a good idea to store those credentials in my db, nor do I think Google wants this either.
Is there a reference on how this can be accomplished?
I have this same situation. We are planning a feature where the user is approving access to send email on their behalf, but the actual sending of the messages is executed by a non-interactive process (scheduled task running on an application server).
I think the ultimate answer is a customized IAuthorizationCodeFlow that only supports access with an existing token, and will not execute the authorization process. I would probably have the flow simulate the response that occurs when a user clicks the Deny button on an interactive flow. That is, any need to get an authorization token will simply return a "denied" AuthorizationResult.
My project is still in the R&D phase, and I am not even doing a proof of concept yet. I am offering this answer in the hope that it helps somebody else develop a concrete solution.
While #hurcane's answer more than likely is correct (haven't tried it out), this is what I got working over the past few days. I really didn't want to have to de/serialize data from the file to get this working, so I kinda mashed up this solution
Web app to get customer approval
Using AuthorizationCodeMvcApp from Google.Apis.Auth.OAuth2.Mvc and documentation
Store resulting access & refresh tokens in DB
Use AE.Net.Mail to do initial IMAP access with access token
Backend also uses AE.Net.Mail to access
If token has expired, then use refresh token to get new access token.
I've not done the sending part, but I presume SMTP will work similarly.
The code is based on SO & blog posts:
t = EF object containing token info
ic = new ImapClient("imap.gmail.com", t.EmailAddress, t.AccessToken, AuthMethods.SaslOAuth, 993, true);
To get an updated Access token (needs error handling) (uses the same API as step #1 above)
using (var wb = new WebClient())
{
var data = new NameValueCollection();
data["refresh_token"] = refresh;
data["client_id"] = "(Web app OAuth id)";
data["client_secret"] = "(Web app OAuth secret)";
data["grant_type"] = "refresh_token";
var response = wb.UploadValues(#"https://accounts.google.com/o/oauth2/token", "POST", data);
string Tokens = System.Text.Encoding.UTF8.GetString(response);
var token = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(Tokens);
at = token.access_token;
return at;
}

OAuth Authentication to EWS

I'm having trouble getting OAuth credentials to work with EWS in Office 365. At a high level I'm writing a SharePoint 2013 app and I'm trying to access the user's mailbox data in Exchange. I did verify my EWS code is 'correct' by swapping out the OAuth code for a hard coded username and password and it worked perfectly.
I get a token back using the code below, however I'm getting a 401 when I try to get the access the user's inbox. I left it off for brevity, but I am passing the token into a new OAuthCredentials object before accessing the inbox.
string acsUrl = "https://accounts.accesscontrol.windows.net/";
using (WebClient exchangeTokenClient = new WebClient())
{
exchangeTokenClient.BaseAddress = acsUrl;
NameValueCollection requestParams = new NameValueCollection();
requestParams.Add("grant_type", "client_credentials");
requestParams.Add("client_id", "<clientid>#<realm>");
requestParams.Add("client_secret", "<client secret>");
requestParams.Add("resource", "00000002-0000-0ff1-ce00-000000000000/outlook.office365.com#<realm>");
exchangeTokenClient.Headers.Add("Authorization", "Bearer " + ((SharePointAcsContext)spContext).UserAccessTokenForSPAppWeb);
byte[] responseBytes = exchangeTokenClient.UploadValues("<realm>/tokens/OAuth/2", "POST", requestParams);
string response = Encoding.UTF8.GetString(responseBytes);
}
The more that I think about this, the more I wonder if my 'app' needs rights on the exchange server and if that is what the root cause of the 401 is.
Has anyone actually done this? I feel like it should be possible, but I can't seem to find a lot of documentation on the process.
Thanks
Joe
Part #1:
Hi Joe, you can't quite do it this way. It seems you try to re-play a SharePoint token to the Exchange endpoint. Exchange will reject the SharePoint token, as the token is not for the Exchange endpoint (it fails the audience check).
Now to get it to work if you want to do Auth the only way for Exchange is to use the new OAuth2 model we announced at SPC. You can get more details from my session presentation at "http://www.sharepointconference.com/content/sessions/SPC379" (I believe we post the slides in a few days). There are three documents out there that I can also recommend to take a look, that is: Authentication and authorization using Common Consent Framework: "http://msdn.microsoft.com/en-us/library/dn605895(v=office.15).aspx", ...
Part #2
... How to: Integrate O365 with a web server app using Common Consent Framework at "http://msdn.microsoft.com/en-us/library/dn605894(v=office.15).aspx" and "Using the Mail, Calendar, and Contact REST APIs to work with emails, calendar items, and contacts" at "http://msdn.microsoft.com/en-us/library/dn605896(v=office.15).aspx"
Hope this helps,
Cheers!
Matthias

Resources