Currently working on an app that is connecting to Azure Mobile Services, and needs to require a Microsoft Account to authenticate.
I have been following this guide:
http://azure.microsoft.com/en-us/documentation/articles/mobile-services-dotnet-backend-windows-universal-dotnet-get-started-users/ Unforunately I have run into this error: Only https scheme is allowed. and I am not entirely sure on how to fix it.
Screenshot of error: http://i.stack.imgur.com/hod9i.png
My code is as follows and comes from the guide listed above.
private async void executiveLoginBtn_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
await AuthenticateAsync();
}
// Define a member variable for storing the signed-in user.
private MobileServiceUser user;
// Define a method that performs the authentication process
// using a Facebook sign-in.
private async System.Threading.Tasks.Task AuthenticateAsync()
{
while (user == null)
{
string message;
try
{
// Change 'MobileService' to the name of your MobileServiceClient instance.
// Sign-in using Facebook authentication.
user = await App.MobileService
.LoginAsync(MobileServiceAuthenticationProvider.MicrosoftAccount);
message =
string.Format("You are now signed in - {0}", user.UserId);
}
catch (InvalidOperationException)
{
message = "You must log in. Login Required";
}
var dialog = new MessageDialog(message);
dialog.Commands.Add(new UICommand("OK"));
await dialog.ShowAsync();
}
}
The error also says "WinRT Information: URI Scheme is not https" - so how could I go about making the URI scheme https or otherwise fixing this error when authenticating to Azure Mobile Services?
1) Select the local MobileService project in Solution Explorer.
2) In the Properties window, change SSL Enabled to True.
3) Take note of the SSL URL and use that address to initialize the MobileServiceClient object in your client application.
How I fix the error is as follows:
SSL Enabled to True.
http://azure.microsoft.com/en-us/documentation/articles/mobile-services-how-to-register-microsoft-authentication/
Input to Redirect URL
App.xaml.cs
public static MobileServiceClient MobileService = new MobileServiceClient("http://service.azure-mobile.net/", "---------------------");
Change to
public static MobileServiceClient MobileService = new MobileServiceClient("https://service.azure-mobile.net/", "---------------------");
Related
I'm trying to implement Firebase Authentication system in my Unity Game Project. Everything is setup properly on the console panel on the website. I've read the docs and can't find a way to login into Google using any api within Firebase within Unity. So I bought Prime31's Play GameServices Plugin for Unity.
Here are my questions:
How to authenticate using Google right within Firebase? Do I need to manage the google sign in myself?
In the Firebase docs I did find:
"After a user successfully signs in, exchange the access token for a Firebase credential, and authenticate with Firebase using the Firebase credential:"
Firebase.Auth.Credential credential = Firebase.Auth.GoogleAuthProvider.GetCredential(googleIdToken, googleAccessToken);
auth.SignInWithCredentialAsync(credential).ContinueWith(task => {
//......//
});
How can I get the googleIdToken, googleAccessToken which are being passed as parameters above?
Please help (with code). I really like Firebase and would like to make it work without any third party plugins like PRIME31.
Here is the entirety of my Google SignIn code w/ Firebase Authentication and GoogleSignIn libraries:
private void SignInWithGoogle(bool linkWithCurrentAnonUser)
{
GoogleSignIn.Configuration = new GoogleSignInConfiguration
{
RequestIdToken = true,
// Copy this value from the google-service.json file.
// oauth_client with type == 3
WebClientId = "[YOUR API CLIENT ID HERE].apps.googleusercontent.com"
};
Task<GoogleSignInUser> signIn = GoogleSignIn.DefaultInstance.SignIn();
TaskCompletionSource<FirebaseUser> signInCompleted = new TaskCompletionSource<FirebaseUser>();
signIn.ContinueWith(task =>
{
if (task.IsCanceled)
{
signInCompleted.SetCanceled();
}
else if (task.IsFaulted)
{
signInCompleted.SetException(task.Exception);
}
else
{
Credential credential = Firebase.Auth.GoogleAuthProvider.GetCredential(((Task<GoogleSignInUser>)task).Result.IdToken, null);
if (linkWithCurrentAnonUser)
{
mAuth.CurrentUser.LinkWithCredentialAsync(credential).ContinueWith(HandleLoginResult);
}
else
{
SignInWithCredential(credential);
}
}
});
}
The parameter is for signing in with intentions of linking the new google account with an anonymous user that is currently logged on. You can ignore those parts of the method if desired. Also note all of this is called after proper initialization of the Firebase Auth libraries.
I used the following libraries for GoogleSignIn: https://github.com/googlesamples/google-signin-unity
The readme page from that link will take you through step-by-step instructions for getting this setup for your environment. After following those and using the code above, I have this working on both android and iOS.
Here is the SignInWithCredential method used in the code above:
private void SignInWithCredential(Credential credential)
{
if (mAuth != null)
{
mAuth.SignInWithCredentialAsync(credential).ContinueWith(HandleLoginResult);
}
}
mAuth is a reference to FirebaseAuth:
mAuth = Firebase.Auth.FirebaseAuth.DefaultInstance;
The simple answer is that there's no way in the Firebase SDK plugin for Unity to do the entirety of Google's authentication in a Unity app. I would recommend following the instructions for email/password sign on to start out.
https://firebase.google.com/docs/auth/unity/start
If you really want Google sign on (which you probably do for a shipping title), this sample should walk you through it: https://github.com/googlesamples/google-signin-unity
The key is to get the id token from Google (which is a separate step from the Firebase plugin), then pass that in.
I hope that helps (even if it wasn't timely)!
For someone asking for HandleLoginResult from #Mathew Coats, here is the function used to handle after.
private void HandleLoginResult(Task<FirebaseUser> task)
{
if (task.IsCanceled)
{
UnityEngine.Debug.LogError("SignInWithCredentialAsync was canceled.");
return;
}
if (task.IsFaulted)
{
UnityEngine.Debug.LogError("SignInWithCredentialAsync encountered an error: " + task.Exception.InnerException.Message);
return;
}
else
{
FirebaseUser newUser = task.Result;
UnityEngine.Debug.Log($"User signed in successfully: {newUser.DisplayName} ({newUser.UserId})");
}
}
As first, you need use Google Sign in Unity plugin to login with Google, and then, when you logged, get token and continues with Firebase Auth. Also you can try this asset http://u3d.as/JR6
Here is the code to get access token from firebase after authentication is done
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
mUser.getToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
#Override
public void onComplete(#NonNull Task<GetTokenResult> task) {
if (dialog != null) {
dialog.dismiss();
}
if (task.isSuccessful()) {
String idToken = task.getResult().getToken();
Log.i(getClass().getName(), "got access token :" + idToken);
} else {
// show logs
}
}
});
My code snippet below is supposed to return the list of beacons. When having Google API Console generate an API Key I have whitelisted my public IP address and associated with the api key. When the code calls ExecuteAsync() method, I keep receiving an exception with error code 403 (forbidden). What may have I done wrong and how to mitigate the issue?
public async void TestApiKey()
{
var apikey = "739479874ABCDEFGH123456"; //it's not the real key I'm using
var beaconServices = new ProximitybeaconService(new Google.Apis.Services.BaseClientService.Initializer
{
ApplicationName = "My Project",
ApiKey = apikey
});
var result = await beaconServices.Beacons.List().ExecuteAsync();
// Display the results.
if (result.Beacons != null)
{
foreach (var api in result.Beacons)
{
Console.WriteLine(api.BeaconName + " - " + api.Status);
}
}
}
You are using a Public API key. Public API keys only work with public data.
beacons.list Authenticate using an OAuth access token from a
signed-in user with viewer, Is owner or Can edit permissions.
Requires the following OAuth scope:
•https://www.googleapis.com/auth/userlocation.beacon.registry
The method you are trying to access is accessing private user data. You need to be authentication before you can use it. Switch to Oauth2 authentication. Setting it to public probably wont work because you cant to my knowledge supply a scope to a public api key.
So I wanted the users to login to my app using Microsoft Account
I did all the setup in my mobile service in Azure and this is how I implement the login in my App:
private async Task<bool> AuthenticateAsync()
{
string message;
bool success = false;
try
{
user = await App.MobileService
.LoginAsync(MobileServiceAuthenticationProvider.MicrosoftAccount);
message =
string.Format("You are now signed in - {0}", user.UserId);
success = true;
}
catch (InvalidOperationException)
{
message = "You must log in. Login Required";
}
var dialog = new MessageDialog(message);
dialog.Commands.Add(new UICommand("OK"));
await dialog.ShowAsync();
return success;
}
all is working fine but all I get from this is a User Id.
and I need the name of the user that logged in, can anyone help me how should I go about this?
Thanks
and I need the name of the user that logged in, can anyone help me how should I go about this
For UWP app, this is impossible using official managed API. See MobileServiceAuthentication class in here
internal async Task<MobileServiceUser> LoginAsync()
{
string response = await this.LoginAsyncOverride();
if (!string.IsNullOrEmpty(response))
{
JToken authToken = JToken.Parse(response);
// Get the Mobile Services auth token and user data
this.Client.CurrentUser = new MobileServiceUser((string)authToken["user"]["userId"]);
this.Client.CurrentUser.MobileServiceAuthenticationToken = (string)authToken[LoginAsyncAuthenticationTokenKey];
}
return this.Client.CurrentUser;
}
The official sdk just retrieves the userId and MobileServiceAuthenticationToken, for other platform, we need to use GetIdentitiesAsync() method to get identity, see How to get user name, email, etc. from MobileServiceUser? or LINK
The username info actually has been retrieved in the SSO process:
So you have to implement the auth process(Extend the method based on the open source code) and maintain the username information as you need.
If you can get the user's input, maybe you can also call Live API: https://msdn.microsoft.com/en-us/library/office/dn659736.aspx#Requesting_info
Every time I try to call the server, I get an error code : ErrorConnectionFailed with Connection failed. Try later. message.
I suspect that it comes from the fact that the credentials of service are empty. Although I have no idea why. If I create the credentials manually using my windows account login and password, it works fine : new WebCredentials(login, password, domain);
I have a console program that works fine (see below), but it does not on a web site.
static void Main(string[] args)
{
var service = GetContextualService(email);
EmailMessage email = EmailMessage.Bind(service, new ItemId(validEmailId));
Console.ReadKey();
}
private static ExchangeService GetContextualService(string email)
{
ExchangeService service = new ExchangeService();
// I don't even need credentials on a Console program to make it work
//service.Credentials = new WebCredentials(CredentialCache.DefaultCredentials);
//service.UseDefaultCredentials = true;
service.AutodiscoverUrl(email, RedirectionUrlValidationCallback);
return service;
}
private static bool RedirectionUrlValidationCallback(string redirectionUrl)
{
// The default for the validation callback is to reject the URL.
bool result = false;
Uri redirectionUri = new Uri(redirectionUrl);
// Validate the contents of the redirection URL. In this simple validation
// callback, the redirection URL is considered valid if it is using HTTPS
// to encrypt the authentication credentials.
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}
While using on a website even with new WebCredentials(CredentialCache.DefaultCredentials);, it returns an exception. (see below)
private ExchangeService GetContextualService(string email)
{
ExchangeService service = new ExchangeService();
service.Credentials = new WebCredentials(CredentialCache.DefaultCredentials);
//service.UseDefaultCredentials = true;
service.AutodiscoverUrl(email, RedirectionUrlValidationCallback);
return service;
}
[HttpPost]
public List<InternetMessageHeader> GetMailHeader(JObject data)
{
ExchangeService service = GetContextualService(data.GetValue("email").Value<string>());
ItemId id = new ItemId(data.GetValue("mailId").Value<string>());
// EXCEPTION BELOW
EmailMessage email = EmailMessage.Bind(service, id);
return email.InternetMessageHeaders.ToList();
}
Why does any call to EWS returns me an exception ?
Why is it working fine on a console program and not on a web server ?
Any thought is welcome !
Strictly based on the code you posted, all I can say is that when you call AutoDiscoverUrl() it may not be talking to the same server that you need to talk to with EWS. Altho typically AD and EWS are on the CAS, it's possible (I think) to get an EWS URL that points to some other server. I've not been in the code in the EWS Editor in some time, but if it does not call the Managed API, it might do AD slightly differently. I'd suggest calling out the EWS URL before you try the Bind() and seeing if you can paste it into a browser. (It'll redirect you OWA, but the connection will be proven.) I'd also call out the AD URL in the redirection callback so you know who you're talking to. Sorry I can't be of more help.
I'm trying to use the Google+ API to access info for the authenticated user. I've copied some code from one of the samples, which works fine (below), however I'm having trouble making it work in a way I can reuse the token across app-launches.
I tried capturing the "RefreshToken" property and using provider.RefreshToken() (amongst other things) and always get a 400 Bad Request response.
Does anyone know how to make this work, or know where I can find some samples? The Google Code site doesn't seem to cover this :-(
class Program
{
private const string Scope = "https://www.googleapis.com/auth/plus.me";
static void Main(string[] args)
{
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description);
provider.ClientIdentifier = "BLAH";
provider.ClientSecret = "BLAH";
var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthentication);
var plus = new PlusService(auth);
plus.Key = "BLAH";
var me = plus.People.Get("me").Fetch();
Console.WriteLine(me.DisplayName);
}
private static IAuthorizationState GetAuthentication(NativeApplicationClient arg)
{
// Get the auth URL:
IAuthorizationState state = new AuthorizationState(new[] { Scope });
state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
Uri authUri = arg.RequestUserAuthorization(state);
// Request authorization from the user (by opening a browser window):
Process.Start(authUri.ToString());
Console.Write(" Authorization Code: ");
string authCode = Console.ReadLine();
Console.WriteLine();
// Retrieve the access token by using the authorization code:
return arg.ProcessUserAuthorization(authCode, state);
}
}
Here is an example. Make sure you add a string setting called RefreshToken and reference System.Security or find another way to safely store the refresh token.
private static byte[] aditionalEntropy = { 1, 2, 3, 4, 5 };
private static IAuthorizationState GetAuthorization(NativeApplicationClient arg)
{
// Get the auth URL:
IAuthorizationState state = new AuthorizationState(new[] { PlusService.Scopes.PlusMe.GetStringValue() });
state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
string refreshToken = LoadRefreshToken();
if (!String.IsNullOrWhiteSpace(refreshToken))
{
state.RefreshToken = refreshToken;
if (arg.RefreshToken(state))
return state;
}
Uri authUri = arg.RequestUserAuthorization(state);
// Request authorization from the user (by opening a browser window):
Process.Start(authUri.ToString());
Console.Write(" Authorization Code: ");
string authCode = Console.ReadLine();
Console.WriteLine();
// Retrieve the access token by using the authorization code:
var result = arg.ProcessUserAuthorization(authCode, state);
StoreRefreshToken(state);
return result;
}
private static string LoadRefreshToken()
{
return Encoding.Unicode.GetString(ProtectedData.Unprotect(Convert.FromBase64String(Properties.Settings.Default.RefreshToken), aditionalEntropy, DataProtectionScope.CurrentUser));
}
private static void StoreRefreshToken(IAuthorizationState state)
{
Properties.Settings.Default.RefreshToken = Convert.ToBase64String(ProtectedData.Protect(Encoding.Unicode.GetBytes(state.RefreshToken), aditionalEntropy, DataProtectionScope.CurrentUser));
Properties.Settings.Default.Save();
}
The general idea is as follows:
You redirect the user to Google's Authorization Endpoint.
You obtain a short-lived Authorization Code.
You immediately exchange the Authorization Code for a long-lived Access Token using Google's Token Endpoint. The Access Token comes with an expiry date and a Refresh Token.
You make requests to Google's API using the Access Token.
You can reuse the Access Token for as many requests as you like until it expires. Then you can use the Refresh Token to request a new Access Token (which comes with a new expiry date and a new Refresh Token).
See also:
The OAuth 2.0 Authorization Protocol
Google's OAuth 2.0 documentation
I also had problems with getting "offline" authentication to work (i.e. acquiring authentication with a refresh token), and got HTTP-response 400 Bad request with a code similar to the OP's code. However, I got it to work with the line client.ClientCredentialApplicator = ClientCredentialApplicator.PostParameter(this.clientSecret); in the Authenticate-method. This is essential to get a working code -- I think this line forces the clientSecret to be sent as a POST-parameter to the server (instead of as a HTTP Basic Auth-parameter).
This solution assumes that you've already got a client ID, a client secret and a refresh-token. Note that you don't need to enter an access-token in the code. (A short-lived access-code is acquired "under the hood" from the Google server when sending the long-lived refresh-token with the line client.RefreshAuthorization(state);. This access-token is stored as part of the auth-variable, from where it is used to authorize the API-calls "under the hood".)
A code example that works for me with Google API v3 for accessing my Google Calendar:
class SomeClass
{
private string clientID = "XXXXXXXXX.apps.googleusercontent.com";
private string clientSecret = "MY_CLIENT_SECRET";
private string refreshToken = "MY_REFRESH_TOKEN";
private string primaryCal = "MY_GMAIL_ADDRESS";
private void button2_Click_1(object sender, EventArgs e)
{
try
{
NativeApplicationClient client = new NativeApplicationClient(GoogleAuthenticationServer.Description, this.clientID, this.clientSecret);
OAuth2Authenticator<NativeApplicationClient> auth = new OAuth2Authenticator<NativeApplicationClient>(client, Authenticate);
// Authenticated and ready for API calls...
// EITHER Calendar API calls (tested):
CalendarService cal = new CalendarService(auth);
EventsResource.ListRequest listrequest = cal.Events.List(this.primaryCal);
Google.Apis.Calendar.v3.Data.Events events = listrequest.Fetch();
// iterate the events and show them here.
// OR Plus API calls (not tested) - copied from OP's code:
var plus = new PlusService(auth);
plus.Key = "BLAH"; // don't know what this line does.
var me = plus.People.Get("me").Fetch();
Console.WriteLine(me.DisplayName);
// OR some other API calls...
}
catch (Exception ex)
{
Console.WriteLine("Error while communicating with Google servers. Try again(?). The error was:\r\n" + ex.Message + "\r\n\r\nInner exception:\r\n" + ex.InnerException.Message);
}
}
private IAuthorizationState Authenticate(NativeApplicationClient client)
{
IAuthorizationState state = new AuthorizationState(new string[] { }) { RefreshToken = this.refreshToken };
// IMPORTANT - does not work without:
client.ClientCredentialApplicator = ClientCredentialApplicator.PostParameter(this.clientSecret);
client.RefreshAuthorization(state);
return state;
}
}
The OAuth 2.0 spec is not yet finished, and there is a smattering of spec implementations out there across the various clients and services that cause these errors to appear. Mostly likely you're doing everything right, but the DotNetOpenAuth version you're using implements a different draft of OAuth 2.0 than Google is currently implementing. Neither part is "right", since the spec isn't yet finalized, but it makes compatibility something of a nightmare.
You can check that the DotNetOpenAuth version you're using is the latest (in case that helps, which it might), but ultimately you may need to either sit tight until the specs are finalized and everyone implements them correctly, or read the Google docs yourself (which presumably describe their version of OAuth 2.0) and implement one that specifically targets their draft version.
I would recommend looking at the "SampleHelper" project in the Samples solution of the Google .NET Client API:
Samples/SampleHelper/AuthorizationMgr.cs
This file shows both how to use Windows Protected Data to store a Refresh token, and it also shows how to use a Local Loopback Server and different techniques to capture the Access code instead of having the user enter it manually.
One of the samples in the library which use this method of authorization can be found below:
Samples/Tasks.CreateTasks/Program.cs