Skip to content

Please allow signin in editor #56

Open
@Thaina

Description

@Thaina

I think it easy just use HttpListener to handle login flow from desktop browser. Please add official support into this repo

I have implement quick basic ISignInImpl for getting idToken to be used in firebase auth and this code below work. I use Newtonsoft.Json.Linq package and some custom extension methods which might not get along with code in this repo so I don't make a pull request. But it possible and it make developing auth smoothly

// Tweak GoogleSignIn.cs a bit

    /// <summary>
    /// Singleton instance of this class.
    /// </summary>
    /// <value>The instance.</value>
    public static GoogleSignIn DefaultInstance {
      get {
        if (theInstance == null) {
#if UNITY_EDITOR
          theInstance = new GoogleSignIn(new GoogleSignInImplEditor(Configuration));
#elif UNITY_ANDROID || UNITY_IOS
          theInstance = new GoogleSignIn(new GoogleSignInImpl(Configuration));
#else
          theInstance = new GoogleSignIn(null);
          throw new SignInException(
              GoogleSignInStatusCode.DeveloperError,
              "This platform is not supported by GoogleSignIn");
#endif
        }
        return theInstance;
      }
    }

    internal GoogleSignIn(ISignInImpl impl) {
      this.impl = impl;
    }
// new file
namespace Google
{
  public static class GoogleSignInEditorConfig
  {
    public static string Secret;
  }
}

namespace Google.Impl
{
  using System;
  using System.Linq;
  using System.Text;

  using System.Net;
  using System.Net.NetworkInformation;

  using UnityEngine;

  using Newtonsoft.Json.Linq;

  internal class GoogleSignInImplEditor : ISignInImpl, FutureAPIImpl<GoogleSignInUser>
  {
    GoogleSignInConfiguration configuration;

    public bool Pending { get; private set; }

    public GoogleSignInStatusCode Status { get; private set; }

    public GoogleSignInUser Result { get; private set; }

    public GoogleSignInImplEditor(GoogleSignInConfiguration configuration)
    {
      this.configuration = configuration;
    }

    public void Disconnect()
    {
      throw new NotImplementedException();
    }

    public void EnableDebugLogging(bool flag)
    {
      throw new NotImplementedException();
    }

    public Future<GoogleSignInUser> SignIn()
    {
      SigningIn();
      return new Future<GoogleSignInUser>(this);
    }

    public Future<GoogleSignInUser> SignInSilently()
    {
      SigningIn();
      return new Future<GoogleSignInUser>(this);
    }

    public void SignOut()
    {
      throw new NotImplementedException();
    }

    static HttpListener BindLocalHostFirstAvailablePort()
    {
      ushort minPort = 49215;
      var listeners = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners();
      return Enumerable.Range(minPort,ushort.MaxValue - minPort).Where((i) => !listeners.Any((x) => x.Port == i)).Select((port) => {
        try
        {
          var listener = new HttpListener();
          listener.Prefixes.Add($"http://localhost:{port}/");
          listener.Start();
          return listener;
        }
        catch
        {
          return null;
        }
      }).FirstOrDefault((listener) => listener != null);
    }

    void SigningIn()
    {
      Pending = true;
      var httpListener = BindLocalHostFirstAvailablePort();
      Application.OpenURL("https://accounts.google.com/o/oauth2/v2/auth?scope=email%20profile&response_type=code&redirect_uri=" + httpListener.Prefixes.FirstOrDefault() + "&client_id=" + configuration.WebClientId);
      httpListener.GetContextAsync().ContinueWith((task) => {
        var context = task.Result;

        string code;
        if(!context.Request.Url.ParseQueryString().TryGetValue("code",out code) || string.IsNullOrEmpty(code))
        {
          Pending = false;
          Status = GoogleSignInStatusCode.InvalidAccount;
          Debug.Log("no code?");
          return;
        }

        context.Response.StatusCode = 200;
        context.Response.OutputStream.Write(Encoding.UTF8.GetBytes("Can close this page"));
        context.Response.Close();

        HttpWebRequest.CreateHttp("https://www.googleapis.com/oauth2/v4/token").PostFormUrlEncoded("code=" + code + "&client_id=" + configuration.WebClientId + "&client_secret=" + GoogleSignInEditorConfig.Secret + "&redirect_uri=" + httpListener.Prefixes.FirstOrDefault() + "&grant_type=authorization_code").ContinueWith((dataTask) => {
          var jobj = JObject.Parse(dataTask.Result);
          Result = new GoogleSignInUser() {
            IdToken = (string)jobj.GetValue("id_token")
          };

          Status = GoogleSignInStatusCode.Success;
          Pending = false;
        });
      });
    }
  }
}
// usage


#if UNITY_EDITOR
			GoogleSignInEditorConfig.Secret	= "{APP_SECRET}";
#endif

			GoogleSignIn.Configuration = new GoogleSignInConfiguration() {
				RequestIdToken = true,
				WebClientId	= "APP_CLIENT_ID",
			};

			var googleUser	= await GoogleSignIn.DefaultInstance.SignIn();

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions