What is the url for Facebook authentication with WebAuthenticationCoreManager - c#

I have this code for Facebook authentication
var scopes = "email user_birthday user_events user_friends user_about_me";
WebAccountProvider facebookAccountProvider =
await WebAuthenticationCoreManager
.FindAccountProviderAsync("https://www.facebook.com/dialog/oauth");
WebTokenRequest webTokenRequest = new WebTokenRequest(facebookAccountProvider, scopes);
WebAuthenticationCoreManager does not like Facebook OAuth endpoint https://www.facebook.com/dialog/oauth and sets my facebookAccountProvider to null.
Does anyone know how I can get FindAccountProviderAsync working with Facebook?

WebAuthenticationCoreManager.FindAccountProviderAsync() finds account providers that have been registered with Windows. This means (say) the Facebook app would need to support it (which it doesn't). At the moment it's only useful for Microsoft accounts and organizational accounts (Office 365/Azure AD).
If you want to use Facebook's OAuth 2.0 implementation directly you can use WebAuthenticationBroker instead (there are examples on that page).

Related

Azure AD authentication failing when using ms live accounts other than my AAD acount

I trying to read user data from their Microsoft live account. I have written code as below:
public void GetUserData(){
var authContext = new AuthenticationContext("https://login.microsoftonline.com/common/");
var result = _authenticationContext
.AcquireTokenAsync("https://graph.microsoft.com", "<my client/app ID>", "<redirect URI>", new PlatformParameters(PromptBehavior.RefreshSession))
.Result;
var accessToken = result.AccessToken;
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",accessToken);
var userResponse = httpClient.GetStringAsync("https://graph.microsoft.com/beta/me/").Result;
//DO SOMTHING WITH DATA
}
my code is working fine when I used my AAD credentials, but when I used my personal account it is giving the following error.
AADSTS50020: User account 'XXXX#outlook.com' from identity provider
'live.com' does not exist in tenant 'Default Directory' and cannot
access the application 'XXXXXXXXXXXXXXXXX' in that
tenant. The account needs to be added as an external user in the
tenant first. Sign out and sign in again with a different Azure Active
Directory user account.
Here is the screenshot:
It's similar to this question. could someone help me out?
v1 endpoints require that the user is a member in a directory.
You should probably use the v2.0 endpoints for this: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-appmodel-v2-overview
If you expect only consumer MS accounts to login, you can specify the authorize URL as:
https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize
First, for the error massage in your question, you need to add the live account into your directory first and then try to use Azure AD v2 endpoint to authenticate. You can not sign in the app with the external account which was not in that directory.
I assume that you want any Microsoft live account can use your app.
Based on this requirement, I suggest you can use Azure AD B2C to achieve this. Azure AD B2C can enables your application to authenticate with any Microsoft account. You can add Microsoft Account as a social identity providers. So that any live accounts can sign up and sign in your App through Azure AD B2C.
You can see more details about Providing sign-up and sign-in to consumers with Microsoft accounts in this official document.
Hope this helps.

On-Behalf-Of Azure Mobile backend - MS Graph

Another attempt to ask a different question surrounding my month long problem:
I'm now trying to initiate the "On-Behalf-Of" flow to get a MS Graph token when users login with a Microsoft Account. As documented here:
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols-oauth-on-behalf-of
On the client, users log in with a server-flow:
var user = await MobileService.LoginAsync(MobileServiceAuthenticationProvider.MicrosoftAccount);
On the .NET backend, I am trying to retrieve the MS Graph token:
string clientId = "id-shown-in-app-registration-portal";
string clientSecret = "secret-shown-in-app-registration-portal";
IEnumerable<string> msIdTokenOut = null;
Request.Headers.TryGetValues("x-ms-token-microsoftaccount-access-token", out msIdTokenOut);
string msIdToken = msIdTokenOut.FirstOrDefault();
AuthenticationContext authContext = new AuthenticationContext("https://login.microsoftonline.com/common/oauth2/v2.0");
UserAssertion assertion = new UserAssertion(msIdToken);
ClientCredential cred = new ClientCredential(clientId, clientSecret);
AuthenticationResult authResult = await authContext.AcquireTokenAsync("https://graph.microsoft.com/", cred, assertion);
I get the following error:
aadsts50027: invalid jwt token. token format not valid.
I've tried every possible combination, from using server-flow to login, using MSAL for client-flow (which doesn't authenticate against App Services with the retrieved token). This has been driving me crazy for over a month. I can't believe how many hoops I have jumped through to get 2 Microsoft products working together. If anyone can steer me towards a solution I would be beyond grateful.
Here is a workaround, I suggest you could enable the mobile server custom authentication by using MSAL returned access token.
More details, you could refer to below steps:
Firstly, you could create a login page which will use MSAL login with the microsoft account. It will return the access token.
Then you could send the request with the access token to the mobile service backend to ask for authentication.
Notice: The logic in the backend which used to check the access token is right, you need achieve by yourself. You could decode the access jwt token to get the aud value. If this value is as same as the client id that means the user have the permission to access mobile backend data.
Then you could use jwt token to get the user information from graph api. After get the user information, you could set the user information value to claims to generate the auth token(using this method AppServiceLoginHandler.CreateToken[Add Microsoft.Azure.Mobile.Server.Login NuGet package]). By using this token the mobile client user could access the mobile backend.
The access token like this:
More details, you could refer to this article to know how to enable custom auth in mobile backend.

Consume Office 365 REST API Without UI

I need to push calendar entries in to a client's Outlook account. This is fairly straight forward with Exchange. You just authenticate with a user that has access, and then you can push entries in to other user's accounts. It seems to be completely different in Office 365.
I tried to follow the instructions here:
https://dev.outlook.com/restapi/getstarted
I created the app and got the app's client ID. But, all of the documentation is around oAuth. Generally speaking, oAuth is designed for scenarios when a user needs to enter their credentials in through a browser window that will then confirm with the user which credentials they are willing to allow the app to have.
This does not match my scenario. I need to be able to push the calendar entries in to the account without any UI. This is back end integration. It just needs to do its job silently.
I looked at this sample app:
https://github.com/OfficeDev/O365-Win-Snippets
But, this is a front end app. When it needs to authenticate, it pops up a window to force the user to enter their credentials.
When I try to call the REST API that is mentioned in the getting started page, it returns HTML. This is the Url it mentions:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F&response_type=code&scope=https%3A%2F%2Foutlook.office.com%2Fmail.read
I've tried a few permutations of this Url with my client ID. I've tried passing in my Office 365 credentials through basic http authentication.
I'm stuck.
The answer is simple. Use the Exchange API - not Office 365 API.
I was confused because I assumed that Office 365 was a different entity to Exchange, but the Office 365 email server just is one giant Exchange server. Here's some sample code for good measure. This is an example of logging in to Office 365's Exchange server and sending off a calendar entry to an email address. Simple.
I made a wild guess about the exchange Url and it was correct:
https://outlook.office365.com/ews/exchange.asmx
//Connect to exchange
var ewsProxy = new ExchangeService(ExchangeVersion.Exchange2013);
ewsProxy.Url = new Uri("https://outlook.office365.com/ews/exchange.asmx");
//Create the meeting
var meeting = new Appointment(ewsProxy);
ewsProxy.Credentials = new NetworkCredential(_Username, _Password);
meeting.RequiredAttendees.Add(_Recipient);
// Set the properties on the meeting object to create the meeting.
meeting.Subject = "Meeting";
meeting.Body = "Please go to the meeting.";
meeting.Start = DateTime.Now.AddHours(1);
meeting.End = DateTime.Now.AddHours(2);
meeting.Location = "Location";
meeting.ReminderMinutesBeforeStart = 60;
// Save the meeting to the Calendar folder and send the meeting request.
meeting.Save(SendInvitationsMode.SendToAllAndSaveCopy);
My understanding is that this is possible, but the authentication looks quite complicated. For starters, any application that requires Office 365 integration must also integrate with the associated Azure AD. You can register your application for specific users so that it has the permissions required for whatever operations you need to perform. See here for a good summary of this component: https://msdn.microsoft.com/en-us/office/office365/howto/connect-your-app-to-o365-app-launcher?f=255&MSPPError=-2147217396#section_2
For authentication, you require a daemon/server application model. I've not attempted this yet, but it's documented here and looks like it should meet your needs (see the Daemon or Server Application to Web API section): https://azure.microsoft.com/en-us/documentation/articles/active-directory-authentication-scenarios/#daemon-or-server-application-to-web-api
In order to call the Office 365 REST API, the app requires an access token from Azure Active Directory, that's why you need (mandatory) to register app in Microsoft Azure Active Directory (Azure AD). Your Office 365 account in turn needs to be associated with Azure AD. This answer summarizes on how to register app in Azure AD in order to consume Office 365 API.
Basic authentication scheme
Regrading Basic authentication, currently it is enabled for API version 1.0, the following example demonstrates how to consume Outlook Calendar REST API in .NET application.
Prerequisites:
domain: https://outlook.office365.com/
API version: v1.0
Here is an example that gets my calendars and prints its names
private static async Task ReadCalendars()
{
var handler = new HttpClientHandler();
handler.Credentials = new NetworkCredential()
{
UserName = ConfigurationManager.AppSettings["UserName"],
Password = ConfigurationManager.AppSettings["Password"]
};
using (var client = new HttpClient(handler))
{
var url = "https://outlook.office365.com/api/v1.0/me/calendars";
var result = await client.GetStringAsync(url);
var data = JObject.Parse(result);
foreach (var item in data["value"])
{
Console.WriteLine(item["Name"]);
}
}
}

Youtube API V3 authentication. Uploading to shared account

I'm trying to update an existing Asp.Net application using C# to avoid the Youtube V2 API deprecation. The 1st challenge is figuring out how to authenticate using the new API.
This is how the application currently authenticates:
string developerKey = (My Developer Key here);
string username = (My username here);
string password = (My password here);
ytService = new YouTubeService("SampleApplication", developerKey);
ytService.setUserCredentials(username, password);
I've researched, and reviewed the V3 API examples, and they all use OAuth2 to Authenticate like this:
UserCredential credential;
using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
// This OAuth 2.0 access scope allows an application to upload files to the
// authenticated user's YouTube channel, but doesn't allow other types of access.
new[] { YouTubeService.Scope.YoutubeUpload },
"user",
CancellationToken.None
);
}
However, that prompts the user to login to their own Google account, and for this application we want all uploaded videos to go into our account. Therefore I would like to continue using the Public API access if possible, and I can't find any examples of this for the V3 APIs.
I've also investigated OAuth2 Service Account, but for the life of me can not figure out how to authenticate using one of those.
Can you help point me in the right direction?
I faced a similar issue recently, except I was working with a shared Google Calendar instead of a Youtube account. What I ended up doing was adding an authorize button that only I could see, which was hooked up to the initial authorize request when clicked. It opened the popup from Google, I gave the permission from the shared account, and I stored the returned access token, refresh token, and expiration date in the database.
Then, whenever users need to view the shared calendar, I just have logic that says if the expiration date has passed, use the stored refresh token to request a new access token and reset the expiration date, then I use the access token to make my Google Calendar API call (getting the events list, in this case).
Unfortunately, V3 of the YouTube API does not support service accounts, and oAuth2 is the only authentication method.
One of the reasons behind this is to do away with having multiple individuals upload into a single account; the legal liability (for both YouTube and app developers) is too great. The only current alternative is the YouTube direct lite program (which has multiple clients ... see YouTube's Github page to find them), which gives you a simple management/admin pane for autogenerating a playlist based on users uploading videos into their own accounts (in other words, they upload the video through your app, to their account, but your account gets a record of it and manages what can/can't appear on the list).

Google Drive simple API Access authorization fail

I'm trying to authorize in google using .NET SDK provided, but it failes with "Invalid credentials" error. I found this answer
Google Calendar V3 2 Legged authentication fails
but I still don't see where is the mistake. Looks like everything is done as described.
Here is my code
const string CONSUMER_KEY = "mytestdomain.com";
const string CONSUMER_SECRET = "my_consumer_secret";
const string TARGET_USER = "user";
const string SERVICE_KEY = "some_api_key";
var auth = new OAuth2LeggedAuthenticator(CONSUMER_KEY, CONSUMER_SECRET, TARGET_USER, CONSUMER_KEY);
var service = new DriveService(auth) { Key = SERVICE_KEY };
var results = service.Files.List().Fetch();
Console.WriteLine(results.Items.Count);
and here are screenshots from google control panel. I just replaced domain name, consumer key and api key.
Screenshot from Manage API client access page
Screenshot from Manage OAuth key and secret for this domain page
Screenshot from API Access page in Google API console
OAuth 1.0 has been deprecated and 2-Legged OAuth 1.0 with it. Although it is still supported for the deprecation period if I were you I would use Service Accounts with OAuth 2.0 to perform domain-wide delegation of authority.
This is very well documented on the Perform Google Apps Domain-wide Delegation of Authority page of the Google Drive SDK documentation.

Categories