Authenticating with Azure EasyTables - Azure ActiveDirectory - azure

I've been attempting to authenticate requests to an Azure App Service for some time now and I'm completely stumped, I just can't seem to get the Microsoft.Azure.Mobile.Client to accept and successfully authenticate against a known "good" token.
Overall, all I want is to be able to successfully pull up a web browser in Xamarin Forms, authenticate the user either with Azure, Google or other social authentication, and then use a token to authenticate against an Azure App Service (EasyTables), which I already have running but without authentication enabled. For some reason none of the resources I've found have provided an clear way of doing this, and I'd be grateful for any help.
Here's the main config of what I have so far:
I've got an app successfully reading and saving data tables to an Azure-hosting EasyTables implementation. Tables are read (and written) using the standard form:
var locations = (await App.MobileService.GetTable<Location>().ToListAsync());
The MobileServiceClient is instantiated in the App.xaml.cs file as follows:
public static MobileServiceClient MobileService = new MobileServiceClient("https://mywebapp.azurewebsites.net");
As I say above, this works fine when access to and saving from online services.
Going to the Azure Portal, I've activated "App Service Authentication" under Settings --> Authentication / Authorization, and I've also set up an Azure Active Directory Authentication Provider. Under this provider I've set up the Client ID of an Azure Active Directory instance (under Manage --> App Registrations).
Going back to Xamarin, I have successfully managed to authenticate against this using the approach by Steven Thewissen here. In particular, I've created an "MSAuthService" helper, which successfully pulls up a web browser, allows you to log in with Microsoft credentials, following which it's able to retrieve your account name and verious other things from Microsoft Graph - including the Access Token.
I'm now trying to use this access token to log into the MobileService I'm using to access EasyTables, using the following:
JObject auth_token_jobject = new JObject();
auth_token_jobject["authenticationToken"] = token;
var output = await App.MobileService.LoginAsync(
MobileServiceAuthenticationProvider.MicrosoftAccount,
auth_token_jobject);
However, whenever I do this, I still get an "Unauthorized" error, produced by the last line above.
I understand that others (e.g. here seemed also to have the same problem, but no resolution on that post.
Other things that I've tried, but haven't managed to get working completely. As above, the closest I've got, by successfully authenticating albeit through Microsoft Graph rather than with my web service specifically, is the process above:
Overview of Authorization with EasyTables etc here - although this doesn't seem to provide any clear code for Xamarin to authenticate against.
Latest Xamarin blog and explanatory materials (here and here, but although the process using await WebAuthenticator.AuthenticateAsync method appears to be a lot simpler than the example I was using above, there doesn't seem to be any detail provided about how you generate the URI required to call the authentication page, nor a step by step guide of how to implement it. Either way, I haven't managed to get it working...
If anyone has an easy way of getting hold of a valid token and then providing it to the MobileService client, I'd be most grateful. I suspect it's as simple of getting the token called back, for example from a Xamarin Essentials WebAuthenticator above, and then passing it with var output = await App.MobileService.LoginAsync(MobileServiceAuthenticationProvider.MicrosoftAccount,auth_token_jobject) but I just can't seem to get it working so far.
Thanks a lot!
Oliver.

There are a couple of issues here (on re-reading it a few times)
You are using MobileServiceAuthenticationProvider.MicrosoftAccount - you should be using "aad" instead.
AAD needs an access token - see https://learn.microsoft.com/en-us/azure/app-service/app-service-authentication-how-to#validate-tokens-from-providers for the details on what needs to be provided.
If the token you get back is really an MSA token, then you still need to provide an access_token field (and not an authenticationToken field)
If you don't need anything special, you should be able to just use .login() like this:
await App.MobileService.LoginAsync("aad", "your-method");
For more details on this, see one of the authentica

Related

Dont get any scopes when calling my Azure AD OAuth web api

I have a web api, using azure ad oauth authentication. I want my associates´ web sites to be able to use this api to display content on their public website. To clearify: No user should be needing consenting/grant anything and they are anonymous.
I have used this guide to set up my web api and this code ("Web Application to Web API"->WebApp-WebAPI-OAuth2-AppIdentity-DotNet-code) for my demo client.
The default scope/permission was assigned to client app in azure portal, like so
The actual problem I trying to solve is my different associates webpages should have different permissions. I was hoping to create different scopes and assign different associates client apps with different scopes and I could check if they for example has update_customer_x-scope.
All this "seems" to work ok. I get my authentication token and I am able to get content from the web api. BUT I dont get any scopes at all. Reading the first guide(web api) I see that you should be able to get the default scope by using the code:
if (ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/scope").Value == "user_impersonation")
{/*you have the default scope*/}
But I dont find anything here, and no scopes at all. Any clues?
This is the content of the JWT-token, as requested
The TodoListController.cs from WebApp-WebAPI-OAuth2-AppIdentity-DotNet just use the client credentials flow as astaykov commented for retrieving the access token without user interaction, at this time, if you decode your code via https://jwt.io/, you would not find the scp property.
For your requirement, you need to follow WebApp-WebAPI-OpenIDConnect-DotNet for calling a web API with the signed-in user's permissions.

Authenticate and Call Sharepoint Online Api from Azure Function

I want to trigger a custom action when a document/file gets added on Sharepoint Online. The idea was to use Microsoft Flow, but as Flow doesn't allow you to work with the custom columns of the file added (just the title, date added, content type, etc), I was thinking of calling the Sharepoint API by hand, via an Azure Function. So the steps would be:
A user adds a new document on a document library on Sharepoint Online
A Microsoft Flow gets triggered after that document gets added.
The Flow calls an Azure Function and pass the document id to it.
The function authenticates to Microsoft Graph Api, and then request for the file with that id.
The function get the custom fields and then it does something with the custom parameters of that file.
However, I ve been trying a lot to authenticate, but it always require me to put user and pass on an HTML. Of course, the Azure Function wouldn't be able to do that. How can I authenticate to Microsoft Graph API easily? I'm stuck with that.
Any other alternative? As I said before, this is a workaround I ve been thinking because Microsoft Flow doesn't allow you to get the custom fields of a recently added/modified file, just the default ones... But what I just want to do is to manage those data when a new file is added. Solution doesn't necessarily need to use a Function or Microsoft Graph Api.
Thanks in advance.
There's not a great way to do the authentication right now - we're working on support for this. The hard part is the AD authentication, which any solution will need to deal with. We're doing some things to make this easy with Functions.
What you can do for auth is get offline access that grants you access to a refresh token, and then use the refresh token to get your access token. You can One way to build this is on Azure Website's existing EasyAuth token store (https://cgillum.tech/2016/03/07/app-service-token-store/). Then you can log in once, save the refresh token in EasyAuth's token store, and the function can pull it from there per execution.
That's the high level answer. I can elaborate on more specific steps if you're eager to do this now.
You could register the function or de Remote Web (Azure or on premise) as an app in your Sharepoint, via URL:
"http://.sharepoint.com/_layouts/15/AppRegNew.aspx
And give it permissions via:
http://.sharepoint.com/_layouts/15/AppInv.aspx
For example:
<AppPermissionRequest Scope="http://sharepoint/content/sitecollection" Right="FullControl" />
</AppPermissionRequests>
In this way you will be capable of accessing your tenant or list or whatever your permissions are.
What you are seeking is app-only authentication. If you can make your document queries/updates via the SharePoint Rest API, then you have 2 options:
Granting access via Azure AD App-Only
Granting access using SharePoint App-Only (This is the same method indicated in #netadictos' answer above.)
If you prefer to make the document queries/updates with the MS Graph API, then only #1 is an option. #1 is a bit more involved, because it requires a client secret AND a self-signed security certificate. #2 will only require the app/client ID and secret.
The MSDN documentation linked above uses a PowerShell script to generate the security cert, but I prefer Bob German's instructions for manually creating/exporting one. He also includes instructions for registering an Azure AD application for your Azure function in his tutorial.

Microsoft Account Authentication in API App on Azure

What I'm hoping to accomplish is a connection to Visual Studio Team Services through the Microsoft Account authentication provider. I've been following the documentation here (https://github.com/Azure/azure-content/blob/master/articles/app-service-api/app-service-api-dotnet-connect-to-saas.md) and have a couple problems with the implementation.
They use the Microsoft.Azure.AppService.ApiApps.Service package to get to the token from the api gateway
// Retrieve the token from the gateway
var runtime = Runtime.FromAppSettings(Request);
var dropboxTokenResult = await runtime.CurrentUser.GetRawTokenAsync("dropbox");
But when I publish my webapp I get a 500 error when trying to create the Runtime object, the remote Debugger literally just dies on the line below and I don't even see any logs in the api's streaming logs interface to give more info on the error.
var runtime = Runtime.FromAppSettings(Request);
Any idea on how to get to the token?
Documenation for implementing microsoftaccount authentication with a web api is kinda scarce, any links to examples or documentation that was helpful to you guys out there?
Also, is the apiapp.json file really even necessary? They create one in the example but authentication setup Via the Azure blades seems to work ok and leaving the apiapp.json file out of the api doesn't seem to matter either way. In the end I'd like my web api to maintain authentication via microsoft account no matter where it's moved to, so I figured there would be settings somewhere I would need to specify but can't really put that piece together either.
It looks like you're using the old model for building API apps (which involves a gateway) which has been deprecated. I believe its still supported, but the official way to build API apps has since changed, and you might find it a bit simpler to work with. More information can be found here: https://azure.microsoft.com/en-us/documentation/articles/app-service-api-whats-changed/
Documentation for leveraging Microsoft Account authentication is here: https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-how-to-configure-microsoft-authentication/
Once you're all set up, there are a few different ways you can obtain the token. You can find it as an inbound HTTP header (x-ms-token-microsoftaccount-access-token) or you can use the App Service Server SDK to obtain it: something alongs the lines of:
var creds = await this.User.GetAppServiceIdentityAsync<MicrosoftAccountCredentials>(this.Request);
string accessToken = creds.AccessToken;

Create a token for Resource Management Node Azure SDK

I've been using the Node Azure SDK over the last few days, everything is going well except for the fact that I cannot find any documentation on how to create an access token for the ResourceManagement API. It seems this doesn't use the PEM + SubId like the other API's in the SDK.
I did find the MSDN docs but they are .Net specific and assume the token is generated via a .dll file. Does anyone have any experience with generating this token via Node?
EDIT:
For reference I have asked on the repo first but have yet to get a response (holiday season)
I think you have to use Active Directory http://blogs.msdn.com/b/tomholl/archive/2014/11/25/unattended-authentication-to-azure-management-apis-with-azure-active-directory.aspx
For anyone else looking to do this:
You need to do a service to service type OAuth call. This is slightly different to authenticating the user as most documents show.
The link below pretty much walks you through it. I've tested in postman (chrome) and have successfully got a token back.
http://msdn.microsoft.com/en-us/library/azure/dn645543.aspx

Oauth2 for SharePoint 365 REST

I'm trying to connect to Sharepoint Online (Sharepoint 365?) content using OAuth2 and the REST API. I need to do this from Python as it is an addition to an existing application. I have already managed to connect the application to Google Drive using OAuth2 and REST, so I think I understand the fundamentals of using OAuth2.
I've tried a number of combinations of places to configure the client_id and client_secret and authenticate and receive access and refresh tokens.
So far I have been able to receive a refresh token and use it to obtain an access token; however, I'm unable to use the access token to access content on the Sharepoint 365 site.
For configuring the client_id and client_secret I associated my Sharepoint site with AAD using the Azure Management Portal. Then I added an application to the Sharepoint AD entry with the client_id and client_secret. In Sharepoint I used appregnew.aspx to register the client_id and verified the application appears in appprincipals.aspx.
I call the authentication service using:
.../login.windows.net/common/oauth2/authorize?api-version=1.0&response_type=code&client_id=&redirect_uri=&resource=Microsoft.Sharepoint
and am able to authenticate, receive a code, call back to
.../login.windows.net/common/oauth2/token with the code and receive access and refresh tokens.
I serialized those tokens and from a separate process call
.../login.windows.net/common/oauth2/token with the refresh_token, client_id, client_secret, and grant_type=refresh_token and receive a new access token.
Finally I call in to Sharepoint service endpoint
-my.sharepoint.com/personal//_api/web/files'
with the new access token and it fails telling me the resource Microsoft.Sharepoint is invalid (Invalid audience Uri 'Microsoft.SharePoint')
I've been spinning my wheels trying various permutations of where the client_id is configured and this is as far as I've gotten. Since all the documentation and examples seem to depend on using C# libraries such as TokenHelper I feel like I'm missing something key but simple and can't find the required information.
Has anyone connected to Sharepoint Online using Python, Ruby, Java, etc? If so:
Where should the client_id be configured?
What are the endpoints for obtaining the refresh and access tokens?
What is the appropriate audience uri or resource for which to request tokens?
Many thanks!
I've successfully connected to SharePoint Online using PHP. It looks to me like you're combining two different methods to do so.
Here is what I did:
Register my app in Azure AD on the Management Portal to get client_id, client_secret, redirectUri and the right permissions on Office 365 for sites.
Call the authorization endpoint at https://login.microsoftonline.com/common/oauth2/authorize
Call the token service endpoint at https://login.microsoftonline.com/common/oauth2/token
Call the SharePoint REST endpoint with the access token.
The resource should be simply the URL of your SharePoint site.
The appregnew.aspx and appprincipals.aspx pages are used for apps for SharePoint but it doesn't look like you're building one.
I think you are trying to do OAuth from Sharepoint Online without creating an Add-In inside Sharepoint. This was the exact problem I was facing. I know this is an old question but my answer might be helpful to someone else coming here.
It is possible to do OAuth from any web-app. Here are the step by step instructions in my blog -
https://medium.com/#yash_agarwal2/performing-oauth-and-rest-calls-with-sharepoint-online-without-creating-an-add-in-677e15c8d6ab#.6pf4wp83b
High Level overview -
1) Get client id and secret by registering yourself here - https://sellerdashboard.microsoft.com/Registration
2) Get Access Token, Refresh Token by following steps here -
https://msdn.microsoft.com/en-us/library/office/jj687470.aspx
Im probably a bit late to the party, but to whoever stumbles into this one, you can have a look at how the SharePoint Oauth App Client lib does it.
You'll probably want to check the SPSite and SPAccessToken classes.
I know this is old by had to deal with similar problem and have 2.5 solutions.
This solution is specifically for the federated logins.
Simple hacky solutions works like a magic for files :)
On Windows 10 - the silliest solution:
First login to your sharepoint with Internet Exploer/Edge. Must be IE/Edge.
Then in Start-> Run dialog or any Windows Explorer address bar do this: \\<your_sharepoint_site.com>#SSL\rest\of_the\path. Note #SSL after host name.
Make sure to replace all the forward slashes with backslashes.
This makes sure that your login credentials are captured by the system.
Then navigate to "This PC", menu "Computer->Map Network Drive" and paste either that same path from above or your normal URL https://<your_sharepoint_site.com>/rest/of_the/path into Folder text field of Map Network Drive.
Now you have Sharepoint folder mapped as regular network drive X:\! Which allows you to treat is just as normal file system folder from any program or programming language.
This solution uses WebDav WebClient and by default you will hit a 50MB limit! Worry not follow these steps to release yourself from the shackles of the silly limit.
Simple Hacky.
Open your browsers and open the 'Developer Tools'.
Navigate to 'Network' tab of 'Developer Tools'
With Network tab open login to your sharepoint site.
Click on any of the requests and you shall see that every single Request Header has a Cookie with FedAuth=some_very_long_base64_encoded_xml_struct;rtFa=something_else_long.
Basically you need these two cookies FedAuth and rtFa.
Now with every GET POST (curl, wget etc) request to the Sharepoint just add a new header Cookie with the value FedAuth=<fedauth-cookie-value>;rtFa=<rtFa-cookie-value>.
Programmatic-hacky (example in python on windows), essentially #2 but cookie manipulation all done programmatically.
We shall steal the cookie directly from the kid... I mean from the Chrome browser.
Navigate to your Sharepoint With the chrome browser and perform all the necessary login actions.
Steal the cookie gist. Plagiarized from here.
Use the cookie gist.
REST of Sharepoint REST API wisdom here and ref here.
Finally open a beer enjoy your day.

Resources