OAuth2 : How to get authorization code from Outlook API for Authentication in Unity?

1.4k views Asked by At

I'm developing a desktop application with Unity and I need to check if the user can log in Outlook to have access to my app.

So, I'm following this process from Microsoft docs and I'm trying to figure out how I can open Outlook API login page and send to my app the authorization code and then get the access-token to finally obtained information about the user. I tried several ways but without success.

First, I tried to obtain a kind of AuthenticationContext like We can use in general C# .NET Application by importing some .dlls but It seems that this solution is just a dream.

Then, I tried this functions I found, but the issue is that Outlook API, like all Microsoft Authentication API (I guess), needs a redirect_uri to send the code and the access-token. If I can get this authorization's code, I think that I could use the functions I found to do what I need. I tried to set a website with a PHP script as redirect_link to get the code and at the same time, do a request to get it. But even if I try to get it through this script with a UnityWebRequest it's not working and It's really an ugly way to do it ^^'

Is there a way to open the Outlook "authorize" page and wait for a response ? Like if I could put the redirect_uri as my desktop application?

I need your help! And is there a better way to do it than mine?

Thanks !

UPDATE : Here is my C# code

private IEnumarator ConnectOutlook()
{
    string client_ID = "client-id";
    string redirect_uri = "link of my PHP script";
    string response_type = "code";
    string url = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=" + client_ID + "&redirect_uri=" + redirect_uri + "&response_type=" + response_type + "&scope=openid";
    Application.OpenURL(url);
    string resultCode = null;
    StartCoroutine(GetAuthorization((code) => resultCode = code));
    yield return new WaitUntil(() => resultCode != null);
StartCoroutine(GetAccessToken(resultCode));
    }

private static IEnumerator GetAuthorization(Action<string> result)
{
    Dictionary<string, string> content = new Dictionary<string, string>();

    content.Add("action", "GetCode");
    UnityWebRequest www = UnityWebRequest.Post("link of my PHP Script", content);
    //Send request
    yield return www.Send();

    yield return new WaitUntil(() => www.downloadHandler.text != "");
    if (!www.isNetworkError)
    {
        string resultContent = www.downloadHandler.text;
        Debug.Log(resultContent);
         result(resultContent);
    }
    else
    {
        //Return null
        result("");
    }
}

private static IEnumerator GetAccessToken(string code)
    {

        Dictionary<string, string> content = new Dictionary<string, string>();
        //Fill key and value

        content.Add("client_id", "client-id");
        content.Add("client_secret", "client_secret");
        content.Add("code", code);
        content.Add("redirect_uri", "link of my PHP Script");
        content.Add("grant_type", "authorization_code");

        UnityWebRequest www = UnityWebRequest.Post("https://login.microsoftonline.com/common/oauth2/v2.0/token", content);
        //Send request
        yield return www.Send();

        if (!www.isNetworkError)
        {
            string resultContent = www.downloadHandler.text;
            TokenClassName json = JsonUtility.FromJson<TokenClassName>(resultContent);

            //Return result
            Debug.Log(json.access_token);
        }
        else
        {
            //Return null
            result("");
        }
    }

public class TokenClassName
{
    public string access_token;
}

And here is my PHP Script (Please don't forget I'm trying to not use this script) :

<?php
    $code = "";
  // Here I get the code when Outlook API is redirecting after log in
  if (isset($_GET['code'])) {
    //Assign the code 
        $code = $_GET['code'];
  }
  elseif (isset($_GET['error'])) {
    exit('ERROR: '.$_GET['error'].' - '.$_GET['error_description']);
  }

  //Here I try to return the assigned code
  if ($_POST["action"] == "GetCode"){
    echo $_GET['code'];
  } 
?>

I'm really looking for a way to disable the redirection to my script. The best should be to use an "await" for a response like in .NET UWP with AuthorizationContext and the way explained HERE

1

There are 1 answers

0
Sergey On

You need to use a loopback redirection URL. For example http://localhost:7000/. Just run a listen server inside Unity that will listen to any call of http://localhost:7000/ URL. Like

TcpListener server = new TcpListener ("http://localhost", 7000); 

You can also have some random session parameters to ensure http://localhost:7000 is called from the propper session that just started.

Check this git-hub repo with examples: https://github.com/zizul/OAuth2.0-Unity/blob/master/Assets/OAuthClient.cs

I've not testes the code. I will update this post after I check it. But it looks like it should work.