I'm building an app that should be able to send emails. I'm using OAuth2 to verify the user, and I've looked at the Xamarin Forms Sample which works great with gmail after setup.
However it doesn't work with my Microsoft account.
I've created a cliendId and all that stuff on Microsoft. Do I have to have a Azure AD as well?
I'm calling the authentication with:
new OAuth2Authenticator(
"myClientId",
"User.Read",
new Uri("https://login.live.com/oauth20_authorize.srf?client_id=myid&scope=user.read&response_type=token&redirect_uri=https://login.live.com/oauth20_desktop.srf"),
new Uri("myRedirectUri"),
null,
true);
But am reaching a screen saying: We cannot perform your request.
Microsoft-accounts is having technical issues right now. Try again later.
Have looked at this sample, where the author uses Google and Microsoft accounts in similar ways.
If I'm instead using this sample it works with the original setup, but not if I change to my own clientId and redirectUrl. Is this since I don't have any Azure account?
Would not like to pay to get it, and since the first approach works fine with my gmail I would love if it could work with Microsoft as well.
/Oliver
Have you tried the microsoftonline.com endpoints instead? I've also implemented this using Xamarin.Auth and could get it working that way.
AuthorizeUrl: https://login.microsoftonline.com/common/oauth2/v2.0/authorize
AccessTokenUrl: https://login.microsoftonline.com/common/oauth2/v2.0/token
"common" is the {tenant} which you can replace with "consumers" if you only wanna allow personal accounts.
An alternative to coding it yourself, is to use a 3rd party library to handle authentication.
CloudRail have SDKs for Xamarin, with build-in integrations for social login/authentication, and also for email sending, which you mention.
Related
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
I ran Google Cloud Security Scanner against my Google App Engine app. I asked it to authenticate against a "Non-Google Account" -- in other words, user-name/password fields in my webapp. However, I get back the message "Could not sign in using the provided username and password" each time.
(I tried it several times, specifying different user-agents and credentials and against two variants of my login page; and of course confirming that the credentials work when typed in manually. I have the necessary Editor-level permissions on the Google Cloud project.)
What do I need to do to get the Scanner to authenticate?
Here's what the docs say about Non-Google account authentication:
Note that support for login forms is still in development, and may not
work out-of-the-box with your system. If you have confirmed your test
account is able to login manually, but not in Cloud Security Scanner,
use the feedback option within the tools to request support.
One possible workaround is to create a simplified alternative login form for the purposes of using the scanner if it's unable to work with the current one.
I am creating a web app and I have implemented authentication using Facebook, Google. Now I want to authenticate using weChat. I understand I need to use "passport-wechat-auth" but for that I need to create wechat account and that throws me failure each time. SO if anyone have better idea to implement it will be very helpful.
Basically you must have a official wechat account to implement. For authentication as like FB etc, you an use WeChat-oauth npm module to do it.
In-Case if you don't have a actual official account. You can use sandbox account for development.Wechat Sandbox
I read these two articles 1.here and 2.here to find out what is best way to perform authentication against an Azure Mobile App when the API on the server is using Claims based custom authorization and the Xamarin client calling it is using the MobileServiceClient framework. I am unable to finalize which of the two examples in those links is the better way to go.
In the first link there doesn't seem to be any dependency on platform specific code like it has in the second link, which means I don't need to write any code in the Driod or IOS or Windows projects and can get away with doing everything in a class library itself.(Am I right here?)
Also, the first link seems to not require any provider like the second link does because I am invoking a direct service call to a Url. The second link on the other hand only seems to support Facebook, Twitter, MicrosoftAccount, Google and WindowsAzureActiveDirectory. The mandatory MobileServiceAuthenticationProvider parameter doesn't seem to provide for Custom Authentication against a sql server based User table. I am not sure about this part and cant find documentation that says otherwise.
If LoginAsync doesn't provide for Custom Authentication then its clear that I will need to follow the InvokeApiAsync route. If it does provide it then the question is: should I write platform specific(Droid/IOS/windows) code in each target project like in the second link or should I handle all the service calls in a class library as can be done in the example shown in the first link? In other words should I go with LoginAsync or InvokeApiAsync? Which of the two is the recommended way?
The first article shows off custom authentication, as you intimated. The second article shows off App Service Authentication, which has a known list. If you need to do a custom username/password, then go with the former. If you need to go with social auth or enterprise auth, then go with the latter.
My general recommendation is don't require the user to create yet another username unless you have to - which means social authentication for consumer apps and enterprise authentication via AAD for enterprise apps.
My other recommendation is to always use the client SDK for doing the authentication part. This allows you to follow the very latest practices from the provider (facebook, twitter, etc.) in respect to security, refresh tokens and other authentication requirements. Once you have the provider token, it's easy to swap it for an Azure Mobile token by using LoginAsync() with a token. See the Azure Documentation for information on this.
In all cases, you are going to need platform specific code - that means using the DependencyService (as in the second example) to execute your login code. I generally create a singleton class that wraps the MobileServiceClient in the PCL. Then create an ILoginProvider interface which has LoginAsync/LogoutAsync code in it to handle the platform dependency code. My singleton class then calls the DependencyService to get the code. You can find an example in my GitHub Repository that covers iOS, Android and UWP.
I have the following scenario:
1.- A web api project in Azure, that I want to secure using Azure AD (I don't mind Token, cookie, whatever, as far as it meets the entire scenario)
2.- An Azure web site in asp.net MVC, also secured by Azure AD. This website has to call the web api controller with SSO (I'm using same Azure AD in the entire scenario)
3.- Some JavaScript code running in a page in SharePoint Online, also calling the web api controller in any secure way (The Office 365 tenant is also using same Azure AD). If you don't know about SharePoint, let's say I have an SPA project where I can only use Javascript and html (no server side code).
Following some of the MS Azure AD samples and some blogs from Vittorio Bertocci I'm able to get the points 1 and 2 working fine, using OWIN and Oppen ID connect. However, seems impossible to achieve point 3. As I'm inside a page in SharePoint Online, I can only use javascript, and not any server side code. I'd like to get a valid token for the current user, that is already logged in SP, and remember that SP uses same Azure AD that web api site.
Can I call the Azure AD and get a valid token, just from client code?
I'm open to any possible solution. I can do whatever in the web api project. If you are thinking in a SharePoint app with an appPart, and the appPart calls the web api from server side code, I agree that will work, but it's an option that is not allowed at the moment :(
Many thanks.
I have similar needs. While waiting for a Microsoft sponsored solution we’re working on the following approach.
3) in Your solution (i.e. HTML page with JavaScript, hosted in SharePoint Online and running in Browser) will call Services in 1) (i.e. Web Api Service layer in Azure).
In Our case we only want to validate that the calls made from SharePoint Online (via users browser, i.e. JavaScript) originate from a correct Office 365 / SharePoint Online user in our tenant.
We are opting out of using the App Model as we only want some simple HTML / JavaScript pages in our Intranet and don’t want App Webs. The Web Api server side code is kind of our “Web Part” code behind.
Change to the solution after trying it out and having workable code:
The auth cookies are ReadOnly and cannot be used. Instead we have registered one metod in our service layer as App in SharePoint Online (via appregnew.aspx). That methods url (e.g. https://cloudservice.customer.com/api/authentication/token) is registered as App start page in the app manifest and is deployed to a site Collection.
Now we can call our App via https://customer.sharepoint.com/sites/devassets/_layouts/15/appredirect.aspx?instance_id={GUID} i a jQuery ajax call and parse the result. AppRedirect sends the correct SPAuthToken which we use in our service endpoint (i.e. App start page) to call back to SharePoint and check context.Web.CurrentUser. User email is then stored in Table Storage with a generated Token which we send back to the caller (i.e. the jQuery ajax call to app redirect).
That token is then used in all other service layer calls in order to be sure of who is calling our service layer and in some cases perform authorization in our service layer.
Note, You can use the same approach in order to store Refresh and AccessToken in your client and provide that in all calls to your service from your client and use those tokens in order to do App Calls back to SharePoint. This enables HTML UI in SharePoint host webs and server code using user context in Azure service layer.
To follow up, ADAL.js has recently been released, and the ability to use CORS with O365 APIs was recently added, enabling a scenario for script clients to communicate with services protected by Azure AD, such as your Web API.
http://www.andrewconnell.com/blog/adal-js-cors-with-o365-apis-files-sharepoint
UPDATE 2018:
This is now supported by SharePoint Online and the SPFx development model, and officially documented, for instance here
Consume enterprise APIs secured with Azure AD in SharePoint Framework
Being said that the work done meanwhile by Vittorio, Kirk, and their teams, but extending that also to Andrew that has delivered great samples, is awesome; that doesn't really fully reply the original question because one of the requirements is to don't run the component as Add-in Part.
If you try to use ADAL JS (which starts its own OAuth flow) hosting that directly in a SP page, that's not going to work, or anyway you can expect a weird behavior for the user (cause of client redirects happening on the browser).
The solution proposed by Peter Karpinski is interesting, and will work matching the requirements in the original question, but requires quite some complexity and additional management/resources.
This recent article provides an alternative solution similar to Peter's one, but requiring less 'extras' and somewhat simpler, also reusing user's SP identity.
Consuming Azure Hosted Web API from SharePoint Online using JavaScript and Office 365 identities
and doesn't either require the use of ADAL on the client side and the implementation of custom security provider / token issuer on the server side.
The identity (cookie) will be passed via properly handling CORS (documentation) on both sides.
However, as you can read in my comments to that blog, this won't work normally with IE due to its security zone implementation. You'll have to be sure you have control on IE security zones on the clients, or have an alternative solution specific for IE.
As of today AAD does not support the OAuth2 implicit flow (or OpenId Connect variants) hence you can't obtain a token from AAD using a user-agent (browser), regardless of whether you hit the wire handcrafting the protocol or using a library.
However keep an eye on future announcements, as this is an important scenario for us!
HTH
Cheers,
V.
update we now support the implicit flow on our server, and we released a library for helping you consume the new feature: http://www.cloudidentity.com/blog/2015/02/19/introducing-adal-js-v1/
Thank youi for r your patience!
The fact that you say you can use only HTML/JS let me guess you're having a SharePoint-hosted App.
Azure AD Authentication Library (ADAL) doesn't provide yet in this moment support for HTML5.
I've been looking since a while (almost one year) on how to implement something as you say; but I couldn't find any working solution, which doesn't make use also of some 'code-behind'.
I'd suggest you then to move to a Provider-hosted App, where you'll be able to have some C# code, and make use of ADAL to retrieve and reuse the OAuth token.
Also, I think is worth to look at this documentation page:
Choose patterns for developing and hosting your app for SharePoint
at section Match your hosting pattern with your development goals
thanks for your help.
Well, it's not a SP-Hosted App, but it's same scenario. It's just a SP page in SP Online, so I can only use JS code like in a SP-hosted app.
As I said in my question, I agree the Provider hosted app is likely the right (or at least, the unique) solution, but that means to build and app, deploy it, and add teh appPart manually to the page (is not easy to package in a WSP). So, this solution is quite hard, when you only want to make some AJAX calls and show some data.
However, after all that I've seen, I think we can't do anything else. I'm gonna wait some more days to see if someone know any weird workarround that could work, and if not, I'll mark your answer as valid.
Thanks again!