🌤

Auth0: implementing a device flow in a Console Application with .NET 7

securitydotnet
Loading...
 

Published on

December 28, 2022

Introduction

How many times have you had to log in from a TV or otherwise from a device where it was difficult to use a keyboard or any other input tool? These are perfect use cases for the device flow authentication. In this authorization flow, a device, asks to you to navigate to a link from another device, insert a code, login with your credentials and then the previous device finalize the login flow when the login flow is done.

It's easy and it's very useful. let's see how easy it is to implement this type of authorization with Auth0.

Register the Application with Auth0

From the Dashboard, create a new Application and select "Native" as application type.

application type

As "Allowed web origin" insert the value "https://auth0.github.io".

https://auth0.github.io

From the "Advanced Settings" make sure you have the following settings:

Advanced Settings

Now we are ready to create a new .NET 7 Console Application and implement the device flow authorization.

Create a new Console Application

From Visual Studio or from command line, create a new Console Application and select .NET 7 as target framework.

Install the Nuget package called "RestSharp". It's not mandatory but it makes easier to call API endpoints from the code.

First of all you need to retrieve the verification url and the user code and show these values to the user.

The following code makes the first call to retrieve the verification url and the user code. There are better way to parse the json, but this post it's not focused on it.

const string tenant = "YOUR-TENANT.us";
const string clientId = "YOUR-CLIENT-ID";
string access_token = string.Empty;

var client = new RestClient($"https://{tenant}.auth0.com/oauth/device/code");
var request = new RestRequest();
request.Method = Method.Post;
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddParameter("application/x-www-form-urlencoded", $"client_id={clientId}&scope=offline_access+openid+profile", ParameterType.RequestBody);
var response = client.Execute(request);

var json = JObject.Parse(response.Content);
var devicecode = json["device_code"].Value<string>();
var user_code = json["user_code"].Value<string>();
var verification_uri = json["verification_uri"].Value<string>();
var interval = json["interval"].Value<int>();
var expires = json["expires_in"].Value<int>();

Console.WriteLine($"Open a browser and paste the url: {verification_uri}, then insert the code: {user_code}");
Console.WriteLine("--------------------------------------------");

Then with the expire value and the interval value, the application should wait the user login and try to retrieve the result based on the interval. There are better way to implement this action.

for (int i = 0; i < (expires / interval); i++)
{
    Task.Delay(interval * 1000).Wait();

    client = new RestClient($"https://{tenant}.auth0.com/oauth/token");
    request = new RestRequest();
    request.Method = Method.Post;
    request.AddHeader("content-type", "application/x-www-form-urlencoded");
    request.AddParameter("application/x-www-form-urlencoded", $"grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code={devicecode}&client_id={clientId}", ParameterType.RequestBody);
    response = client.Execute(request);

    json = JObject.Parse(response.Content);

    if (response.IsSuccessStatusCode)
    {
        access_token = json["access_token"].Value<string>();
        Console.WriteLine($"Your token is: {access_token}");
        break;
    }
    else
    {
        var error = json["error"].Value<string>();
        var error_description = json["error_description"].Value<string>();
        Console.WriteLine($"Status: {error} - {error_description}");
    }
}

With the valid access token, you call call your API endpoint.

client = new RestClient("https://fakerestapi.azurewebsites.net/api/v1/Activities");
request = new RestRequest();
request.Method= Method.Get;
request.AddHeader("content-type", "appliScation/json");
request.AddHeader("authorization", $"Bearer {access_token}");
response = client.Execute(request);

Console.WriteLine("--------------------------------------------");
Console.WriteLine("Response from API:");
Console.WriteLine(response.Content);

Conclusion

This is the basic implementation for the device flow with Auth0. In the next part of the article, we will see how to register an API on the Auth0 Portal and use the refresh token to call the API without the user interation (after the first login).

References

  • https://auth0.com/docs/get-started/authentication-and-authorization-flow/device-authorization-flow
  • https://auth0.com/docs/get-started/authentication-and-authorization-flow/call-your-api-using-the-device-authorization-flow

Create an account to Auth0

If you need an account for Auth0, you can use the following link: https://a0.to/signup-for-auth0. You can use the free version of the service to test your applications and for your development environments.

The entire code of the article

You can find the entire code of the article on my Gist account: https://gist.github.com/kasuken/ef57f1e54e8b0e8092590ae7984da197


Thanks for reading this post, I hope you found it interesting!

Feel free to follow me to get notified when new articles are out 🙂

{% embed https://dev.to/kasuken %}

React, comment and follow on