Auth0: implementing a device flow in a Console Application with .NET 7
Tags: security, dotnet
Published: 2022-12-28 08:15:21

## 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nkiqelajuq9t2bjqc8mo.png)

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

![https://auth0.github.io](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0gkeaay8p6bdim0tj55x.png)

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

![Advanced Settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z2mqazvl4ewfulkdi826.png)

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.

```csharp
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.

```csharp
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.

```csharp
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 %}