diff --git a/main/config/redirects.json b/main/config/redirects.json
index 239030628..5045e7c69 100644
--- a/main/config/redirects.json
+++ b/main/config/redirects.json
@@ -16387,6 +16387,10 @@
"source": "/docs/quickstart/backend/webapi-owin/04-authentication-rs256-deprecated",
"destination": "/docs/quickstart/backend/webapi-owin"
},
+ {
+ "source": "/docs/quickstart/backend/webapi-owin/interactive",
+ "destination": "/docs/quickstart/backend/webapi-owin/index"
+ },
{
"source": "/docs/quickstart/spa/auth0-react/02",
"destination": "/docs/quickstart/spa/react/02-calling-an-api"
diff --git a/main/docs/quickstart/backend/webapi-owin/02-using.mdx b/main/docs/quickstart/backend/webapi-owin/02-using.mdx
deleted file mode 100644
index 6c3114de5..000000000
--- a/main/docs/quickstart/backend/webapi-owin/02-using.mdx
+++ /dev/null
@@ -1,687 +0,0 @@
----
-title: "Auth0 ASP.NET Web API (OWIN) SDK Quickstarts: Using your API"
----
-import {AuthCodeBlock} from "/snippets/AuthCodeBlock.jsx";
-
-import {AuthCodeGroup} from "/snippets/AuthCodeGroup.jsx";
-
-##### By Damien Guard
-
-This tutorial will show you how to use your API. We recommend that you log in to follow this quickstart with examples configured for your account.
-
-## Calling the API From Your Application
-
-You can call the API from your application by passing an Access Token in the `Authorization` header of your HTTP request as a Bearer token.
-
-
-```bash lines
-curl --request GET \
- --url http://localhost:3010/api/private \
- --header 'authorization: Bearer YOUR_ACCESS_TOKEN'
-```
-
-```csharp C# lines
-var client = new RestClient("http://localhost:3010/api/private");
-var request = new RestRequest(Method.GET);
-request.AddHeader("authorization", "Bearer YOUR_ACCESS_TOKEN");
-IRestResponse response = client.Execute(request);
-```
-
-```go Go lines
-package main
-
-import (
- "fmt"
- "net/http"
- "io/ioutil"
-)
-
-func main() {
-
- url := "http://localhost:3010/api/private"
-
- req, _ := http.NewRequest("GET", url, nil)
-
- req.Header.Add("authorization", "Bearer YOUR_ACCESS_TOKEN")
-
- res, _ := http.DefaultClient.Do(req)
-
- defer res.Body.Close()
- body, _ := ioutil.ReadAll(res.Body)
-
- fmt.Println(res)
- fmt.Println(string(body))
-
-}
-```
-
-```java Java lines
-HttpResponse response = Unirest.get("http://localhost:3010/api/private")
- .header("authorization", "Bearer YOUR_ACCESS_TOKEN")
- .asString();
-```
-
-```javascript Node.JS lines
-var axios = require("axios").default;
-
-var options = {
- method: 'GET',
- url: 'http://localhost:3010/api/private',
- headers: {authorization: 'Bearer YOUR_ACCESS_TOKEN'}
-};
-
-axios.request(options).then(function (response) {
- console.log(response.data);
-}).catch(function (error) {
- console.error(error);
-});
-```
-
-
-```php PHP lines
-$curl = curl_init();
-
-curl_setopt_array($curl, [
- CURLOPT_PORT => "3010",
- CURLOPT_URL => "http://localhost:3010/api/private",
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_ENCODING => "",
- CURLOPT_MAXREDIRS => 10,
- CURLOPT_TIMEOUT => 30,
- CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
- CURLOPT_CUSTOMREQUEST => "GET",
- CURLOPT_HTTPHEADER => [
- "authorization: Bearer YOUR_ACCESS_TOKEN"
- ],
-]);
-
-$response = curl_exec($curl);
-$err = curl_error($curl);
-
-curl_close($curl);
-
-if ($err) {
- echo "cURL Error #:" . $err;
-} else {
- echo $response;
-}
-```
-
-```python Python lines
-import http.client
-
-conn = http.client.HTTPConnection("localhost:3010")
-
-headers = { 'authorization': "Bearer YOUR_ACCESS_TOKEN" }
-
-conn.request("GET", "/api/private", headers=headers)
-
-res = conn.getresponse()
-data = res.read()
-
-print(data.decode("utf-8"))
-```
-
-```ruby Ruby lines
-require 'uri'
-require 'net/http'
-
-url = URI("http://localhost:3010/api/private")
-
-http = Net::HTTP.new(url.host, url.port)
-
-request = Net::HTTP::Get.new(url)
-request["authorization"] = 'Bearer YOUR_ACCESS_TOKEN'
-
-response = http.request(request)
-puts response.read_body
-```
-
-
-
-## Obtaining an Access Token
-
-If you are calling the API from a Single-Page Application or a Mobile/Native application, after the authorization flow is completed, you will get an Access Token. How you get the token and how you make the call to the API will be dependent on the type of application you are developing and the framework you are using. For more information refer to the relevant application Quickstarts which contain detailed instructions:
-
-* [Single-Page Applications](/docs/quickstart/spa)
-* [Mobile / Native Application](/docs/quickstart/native)
-
-If you are calling the API from a command-line tool or another service, where there isn't a user entering their credentials, you need to use the [OAuth Client Credentials flow](https://auth0.com/docs/api/authentication#client-credentials). To do that, register a [Machine to Machine Application](https://manage.auth0.com/#/applications), and then subsequently use the **Client ID** and **Client Secret** of this application when making the request below and pass those along in the `client_id` and `client_secret` parameters respectively. Also include the Audience for the API you want to call.
-
-Read [Application Settings](https://auth0.com/docs/get-started/dashboard/application-settings) for more information on getting the Client ID and Client Secret for your machine-to-machine app.
-
-
-```bash cURL
-curl --request POST \
- --url 'https://{yourDomain}/oauth/token' \
- --header 'content-type: application/x-www-form-urlencoded' \
- --data grant_type=client_credentials \
- --data 'client_id={yourClientId}' \
- --data client_secret={yourClientSecret} \
- --data audience=YOUR_API_IDENTIFIER
-```
-```cs C#
-var client = new RestClient("https://{yourDomain}/oauth/token");
-var request = new RestRequest(Method.POST);
-request.AddHeader("content-type", "application/x-www-form-urlencoded");
-request.AddParameter("application/x-www-form-urlencoded", "grant_type=client_credentials&client_id=%24%7Baccount.clientId%7D&client_secret={yourClientSecret}&audience=YOUR_API_IDENTIFIER", ParameterType.RequestBody);
-IRestResponse response = client.Execute(request);
-```
-```go Go
-package main
-
-import (
- "fmt"
- "strings"
- "net/http"
- "io/ioutil"
-)
-
-func main() {
-
- url := "https://{yourDomain}/oauth/token"
-
- payload := strings.NewReader("grant_type=client_credentials&client_id=%24%7Baccount.clientId%7D&client_secret={yourClientSecret}&audience=YOUR_API_IDENTIFIER")
-
- req, _ := http.NewRequest("POST", url, payload)
-
- req.Header.Add("content-type", "application/x-www-form-urlencoded")
-
- res, _ := http.DefaultClient.Do(req)
-
- defer res.Body.Close()
- body, _ := ioutil.ReadAll(res.Body)
-
- fmt.Println(res)
- fmt.Println(string(body))
-
-}
-```
-```java Java
-HttpResponse response = Unirest.post("https://{yourDomain}/oauth/token")
- .header("content-type", "application/x-www-form-urlencoded")
- .body("grant_type=client_credentials&client_id=%24%7Baccount.clientId%7D&client_secret={yourClientSecret}&audience=YOUR_API_IDENTIFIER")
- .asString();
-```
-```javascript Node.JS
-var axios = require("axios").default;
-
-var options = {
- method: 'POST',
- url: 'https://{yourDomain}/oauth/token',
- headers: {'content-type': 'application/x-www-form-urlencoded'},
- data: new URLSearchParams({
- grant_type: 'client_credentials',
- client_id: '{yourClientId}',
- client_secret: '{yourClientSecret}',
- audience: 'YOUR_API_IDENTIFIER'
- })
-};
-
-axios.request(options).then(function (response) {
- console.log(response.data);
-}).catch(function (error) {
- console.error(error);
-});
-```
-```php PHP
-$curl = curl_init();
-
-curl_setopt_array($curl, [
- CURLOPT_URL => "https://{yourDomain}/oauth/token",
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_ENCODING => "",
- CURLOPT_MAXREDIRS => 10,
- CURLOPT_TIMEOUT => 30,
- CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
- CURLOPT_CUSTOMREQUEST => "POST",
- CURLOPT_POSTFIELDS => "grant_type=client_credentials&client_id=%24%7Baccount.clientId%7D&client_secret={yourClientSecret}&audience=YOUR_API_IDENTIFIER",
- CURLOPT_HTTPHEADER => [
- "content-type: application/x-www-form-urlencoded"
- ],
-]);
-
-$response = curl_exec($curl);
-$err = curl_error($curl);
-
-curl_close($curl);
-
-if ($err) {
- echo "cURL Error #:" . $err;
-} else {
- echo $response;
-}
-```
-```python Python
-import http.client
-
-conn = http.client.HTTPSConnection("")
-
-payload = "grant_type=client_credentials&client_id=%24%7Baccount.clientId%7D&client_secret={yourClientSecret}&audience=YOUR_API_IDENTIFIER"
-
-headers = { 'content-type': "application/x-www-form-urlencoded" }
-
-conn.request("POST", "/{yourDomain}/oauth/token", payload, headers)
-
-res = conn.getresponse()
-data = res.read()
-
-print(data.decode("utf-8"))
-```
-```ruby Ruby
-require 'uri'
-require 'net/http'
-require 'openssl'
-
-url = URI("https://{yourDomain}/oauth/token")
-
-http = Net::HTTP.new(url.host, url.port)
-http.use_ssl = true
-http.verify_mode = OpenSSL::SSL::VERIFY_NONE
-
-request = Net::HTTP::Post.new(url)
-request["content-type"] = 'application/x-www-form-urlencoded'
-request.body = "grant_type=client_credentials&client_id=%24%7Baccount.clientId%7D&client_secret={yourClientSecret}&audience=YOUR_API_IDENTIFIER"
-
-response = http.request(request)
-puts response.read_body
-```
-
-
-Auth0 customers are billed based on the number of Machine to Machine Access Tokens issued by Auth0. Once your application gets an Access Token it should keep using it until it expires, to minimize the number of tokens requested.
-
-For testing purposes, you can also get an Access Token from the **Test** tab in your [API settings](https://manage.auth0.com/#/apis).
-
-## Test Your API
-
-**1. Calling the secure endpoint**
-
-You can make a request to the `/api/private` endpoint without passing any Access Token:
-
-
-
-```bash cURL lines
-curl --request GET \
- --url http://localhost:3010/api/private
-```
-```cs C# lines
-var client = new RestClient("http://localhost:3010/api/private");
-var request = new RestRequest(Method.GET);
-IRestResponse response = client.Execute(request);
-```
-
-```go Go lines
-package main
-
-import (
- "fmt"
- "net/http"
- "io/ioutil"
-)
-
-func main() {
-
- url := "http://localhost:3010/api/private"
-
- req, _ := http.NewRequest("GET", url, nil)
-
- res, _ := http.DefaultClient.Do(req)
-
- defer res.Body.Close()
- body, _ := ioutil.ReadAll(res.Body)
-
- fmt.Println(res)
- fmt.Println(string(body))
-
-}
-```
-
-```java Java lines
-HttpResponse response = Unirest.get("http://localhost:3010/api/private")
- .asString();
-```
-
-```javascript Node.JS lines
-var axios = require("axios").default;
-
-var options = {method: 'GET', url: 'http://localhost:3010/api/private'};
-
-axios.request(options).then(function (response) {
- console.log(response.data);
-}).catch(function (error) {
- console.error(error);
-});
-```
-
-```php PHP lines
-$curl = curl_init();
-
-curl_setopt_array($curl, [
- CURLOPT_PORT => "3010",
- CURLOPT_URL => "http://localhost:3010/api/private",
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_ENCODING => "",
- CURLOPT_MAXREDIRS => 10,
- CURLOPT_TIMEOUT => 30,
- CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
- CURLOPT_CUSTOMREQUEST => "GET",
-]);
-
-$response = curl_exec($curl);
-$err = curl_error($curl);
-
-curl_close($curl);
-
-if ($err) {
- echo "cURL Error #:" . $err;
-} else {
- echo $response;
-}
-```
-
-```python Python lines
-import http.client
-
-conn = http.client.HTTPConnection("localhost:3010")
-
-conn.request("GET", "/api/private")
-
-res = conn.getresponse()
-data = res.read()
-
-print(data.decode("utf-8"))
-```
-
-```ruby Ruby lines
-require 'uri'
-require 'net/http'
-
-url = URI("http://localhost:3010/api/private")
-
-http = Net::HTTP.new(url.host, url.port)
-
-request = Net::HTTP::Get.new(url)
-
-response = http.request(request)
-puts response.read_body
-```
-
-
-
-
-The API will return a 401 HTTP (Unauthorized) status code:
-
-
-
-Once again, make the same request but this time pass along the Access Token as a Bearer token in the **Authorization** header of the request:
-
-
-```bash lines
-curl --request GET \
- --url http://localhost:3010/api/private \
- --header 'authorization: Bearer YOUR_ACCESS_TOKEN'
-```
-
-```csharp C# lines
-var client = new RestClient("http://localhost:3010/api/private");
-var request = new RestRequest(Method.GET);
-request.AddHeader("authorization", "Bearer YOUR_ACCESS_TOKEN");
-IRestResponse response = client.Execute(request);
-```
-
-```go Go lines
-package main
-
-import (
- "fmt"
- "net/http"
- "io/ioutil"
-)
-
-func main() {
-
- url := "http://localhost:3010/api/private"
-
- req, _ := http.NewRequest("GET", url, nil)
-
- req.Header.Add("authorization", "Bearer YOUR_ACCESS_TOKEN")
-
- res, _ := http.DefaultClient.Do(req)
-
- defer res.Body.Close()
- body, _ := ioutil.ReadAll(res.Body)
-
- fmt.Println(res)
- fmt.Println(string(body))
-
-}
-```
-
-```java Java lines
-HttpResponse response = Unirest.get("http://localhost:3010/api/private")
- .header("authorization", "Bearer YOUR_ACCESS_TOKEN")
- .asString();
-```
-
-```javascript Node.JS lines
-var axios = require("axios").default;
-
-var options = {
- method: 'GET',
- url: 'http://localhost:3010/api/private',
- headers: {authorization: 'Bearer YOUR_ACCESS_TOKEN'}
-};
-
-axios.request(options).then(function (response) {
- console.log(response.data);
-}).catch(function (error) {
- console.error(error);
-});
-```
-
-
-```php PHP lines
-$curl = curl_init();
-
-curl_setopt_array($curl, [
- CURLOPT_PORT => "3010",
- CURLOPT_URL => "http://localhost:3010/api/private",
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_ENCODING => "",
- CURLOPT_MAXREDIRS => 10,
- CURLOPT_TIMEOUT => 30,
- CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
- CURLOPT_CUSTOMREQUEST => "GET",
- CURLOPT_HTTPHEADER => [
- "authorization: Bearer YOUR_ACCESS_TOKEN"
- ],
-]);
-
-$response = curl_exec($curl);
-$err = curl_error($curl);
-
-curl_close($curl);
-
-if ($err) {
- echo "cURL Error #:" . $err;
-} else {
- echo $response;
-}
-```
-
-```python Python lines
-import http.client
-
-conn = http.client.HTTPConnection("localhost:3010")
-
-headers = { 'authorization': "Bearer YOUR_ACCESS_TOKEN" }
-
-conn.request("GET", "/api/private", headers=headers)
-
-res = conn.getresponse()
-data = res.read()
-
-print(data.decode("utf-8"))
-```
-
-```ruby Ruby lines
-require 'uri'
-require 'net/http'
-
-url = URI("http://localhost:3010/api/private")
-
-http = Net::HTTP.new(url.host, url.port)
-
-request = Net::HTTP::Get.new(url)
-request["authorization"] = 'Bearer YOUR_ACCESS_TOKEN'
-
-response = http.request(request)
-puts response.read_body
-```
-
-
-
-This time the API will return a successful response:
-
-
-
-**2. Testing the scoped endpoint**
-
-To test the endpoint that requires a scope, pass the Access Token containing the correct scope as a Bearer token in the Authorization header:
-
-
-
-```bash cURL lines
-curl --request GET \
- --url http://localhost:3010/api/private-scoped \
- --header 'authorization: Bearer YOUR_ACCESS_TOKEN'
-```
-
-```cs C# lines
-var client = new RestClient("http://localhost:3010/api/private-scoped");
-var request = new RestRequest(Method.GET);
-request.AddHeader("authorization", "Bearer YOUR_ACCESS_TOKEN");
-IRestResponse response = client.Execute(request);
-```
-
-```go Go lines
-package main
-
-import (
- "fmt"
- "net/http"
- "io/ioutil"
-)
-
-func main() {
-
- url := "http://localhost:3010/api/private-scoped"
-
- req, _ := http.NewRequest("GET", url, nil)
-
- req.Header.Add("authorization", "Bearer YOUR_ACCESS_TOKEN")
-
- res, _ := http.DefaultClient.Do(req)
-
- defer res.Body.Close()
- body, _ := ioutil.ReadAll(res.Body)
-
- fmt.Println(res)
- fmt.Println(string(body))
-
-}
-```
-
-```java Java lines
-HttpResponse response = Unirest.get("http://localhost:3010/api/private-scoped")
- .header("authorization", "Bearer YOUR_ACCESS_TOKEN")
- .asString();
-```
-
-```javascript Node.JS lines
-var axios = require("axios").default;
-
-var options = {
- method: 'GET',
- url: 'http://localhost:3010/api/private-scoped',
- headers: {authorization: 'Bearer YOUR_ACCESS_TOKEN'}
-};
-
-axios.request(options).then(function (response) {
- console.log(response.data);
-}).catch(function (error) {
- console.error(error);
-});
-```
-
-
-```php PHP lines
-$curl = curl_init();
-
-curl_setopt_array($curl, [
- CURLOPT_PORT => "3010",
- CURLOPT_URL => "http://localhost:3010/api/private-scoped",
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_ENCODING => "",
- CURLOPT_MAXREDIRS => 10,
- CURLOPT_TIMEOUT => 30,
- CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
- CURLOPT_CUSTOMREQUEST => "GET",
- CURLOPT_HTTPHEADER => [
- "authorization: Bearer YOUR_ACCESS_TOKEN"
- ],
-]);
-
-$response = curl_exec($curl);
-$err = curl_error($curl);
-
-curl_close($curl);
-
-if ($err) {
- echo "cURL Error #:" . $err;
-} else {
- echo $response;
-}
-```
-
-```python Python lines
-import http.client
-
-conn = http.client.HTTPConnection("localhost:3010")
-
-headers = { 'authorization': "Bearer YOUR_ACCESS_TOKEN" }
-
-conn.request("GET", "/api/private-scoped", headers=headers)
-
-res = conn.getresponse()
-data = res.read()
-
-print(data.decode("utf-8"))
-```
-
-```ruby Ruby lines
-require 'uri'
-require 'net/http'
-
-url = URI("http://localhost:3010/api/private-scoped")
-
-http = Net::HTTP.new(url.host, url.port)
-
-request = Net::HTTP::Get.new(url)
-request["authorization"] = 'Bearer YOUR_ACCESS_TOKEN'
-
-response = http.request(request)
-puts response.read_body
-```
-
-
-
-If the required scope is present, the API call is successful:
-
-
-
-If the required scope is not present, the API returns a 403 HTTP Status (Forbidden):
-
-
-
-[Edit on GitHub](https://github.com/auth0/docs/edit/master/articles/quickstart/backend/webapi-owin/02-using.md)
\ No newline at end of file
diff --git a/main/docs/quickstart/backend/webapi-owin/03-troubleshooting.mdx b/main/docs/quickstart/backend/webapi-owin/03-troubleshooting.mdx
deleted file mode 100644
index bb2bbc4dc..000000000
--- a/main/docs/quickstart/backend/webapi-owin/03-troubleshooting.mdx
+++ /dev/null
@@ -1,198 +0,0 @@
----
-title: "Auth0 ASP.NET Web API (OWIN) SDK Quickstarts: Troubleshooting"
----
-
-##### By Damien Guard
-
-This document will help you troubleshoot your configuration if you get a 401 (Unauthorized) response from your API.We recommend that you log in to follow this quickstart with examples configured for your account.
-
-If you configured the JWT middleware correctly, you will be able to get proper responses from your API when you make requests. However, in the case where you get a 401 (Unauthorized) response from your API, it is because the configuration of your JWT middleware does not match with the JWT which was passed.
-
-This document will help you troubleshoot your JWT middleware configuration.
-
-## How does a token get validated?
-
-In terms of validating a JWT, there are various things to consider:
-
-1. **Is the token well-formed?** In other words, is this token conforming to the structure of a JSON Web Token (JWT)? To get more information on the structure of a JWT, please refer to [this section on the structure of a JWT](/docs/secure/tokens/json-web-tokens#what-is-the-json-web-token-structure-)
-2. **Has the token been tampered with?** The last part of a JWT is the signature. The signature is used to verify that the token was in fact signed by the sender and not altered in any way.
-3. **Has the token been received in its validity period?** JWTs are only valid for a specified time period (as expressed in the `exp` claim).
-4. **Is the token coming from the intended Authority?** This consists of 2 parts
-
- * **Signature Verification**: Can we confirm that the JWT is correctly signed using the key issued by the issuing authority?
- * **Issuer Value**: The Issuer is defined in the `iss` claim. Once again does this claim match up with what your application expects?
-5. **Is the token intended for the current application?** So does the `aud` claim of the JWT match with what your application is expecting?
-
-## Inspecting a token
-
-A quick way to inspect a JWT is by using the [JWT.io](https://jwt.io/) website. It has a handy debugger which allows you to quickly check that a JWT is well-formed, and also inspect the values of the various claims.
-
-
-
-In the screenshot above you can see that the token was signed using the **RS256** algorithm. The **Issuer** of the token is **https://jerrie.auth0.com/**, and the **Audience** is **https://quickstarts/api**.
-
-So in other words these values in your JWT middleware registration must match **exactly** - including the trailing slash for the Issuer, such as
-
-```cs lines
-var keyResolver = new OpenIdConnectSigningKeyResolver("https://jerrie.auth0.com/");
-app.UseJwtBearerAuthentication(
- new JwtBearerAuthenticationOptions
- {
- AuthenticationMode = AuthenticationMode.Active,
- TokenValidationParameters = new TokenValidationParameters()
- {
- ValidAudience = "https://quickstarts/api",
- ValidIssuer = "https://jerrie.auth0.com/",
- IssuerSigningKeyResolver = (token, securityToken, kid, parameters) => keyResolver.GetSigningKey(kid)
- }
- });
-```
-
-
-
-
-
-
-For a token signed using HS256, the debugger view will look a little different:
-
-
-
-In the screenshot above you can see that the token was signed using the **HS256** algorithm. The **Issuer** of the token is **https://jerrie.auth0.com/**, and the **Audience** is **https://quickstarts/api/hs256**.
-
-In this case, the middleware needs to be configured as follows:
-
-```cs lines
-app.UseJwtBearerAuthentication(
- new JwtBearerAuthenticationOptions
- {
- AuthenticationMode = AuthenticationMode.Active,
- AllowedAudiences = new[] { "https://quickstarts/api/hs256" },
- IssuerSecurityKeyProviders = new IIssuerSecurityKeyProvider[]
- {
- new SymmetricKeyIssuerSecurityKeyProvider("https://jerrie.auth0.com/",
- Encoding.UTF8.GetBytes("your api secret"))
- }
- });
-```
-
-
-
-
-
-
-## Using the log files to debug configuration issues
-
-In order to inspect the log message which are generated by the OWIN middleware, you need to set the logging level to Verbose. So in your `web.config` file, add the following:
-
-```xml lines
-
-
-
-
-
-```
-
-
-
-
-
-
-This will log all OWIN log messages to the Output window in Visual Studio when running your application in Debug Mode.
-
-### 1. Are you actually passing the JWT in the Authorization header?
-
-The first thing is to ensure that you actually pass along the JWT as a Bearer token in the Authorization header of the request. If you get a 401 (Unauthorized) response from your Web API, but you do not see any other error messages being logged to the Output Window, then most likely you are simply not sending the JWT in the Authorization header of the request.
-
-To resolve this issue, ensure that you send the JWT as a bearer token in the Authorization header.
-
-## 2. Did you configure the JWT middleware for the correct signing algorithm?
-
-Another common mistake is that your tokens are signed using the HS256 [signing algorithm](/docs/get-started/applications/signing-algorithms), but your middleware is configured for RS256 - or vice versa.
-
-In the following screenshot, you can see that we get an error message that the signature validation failed. This is because the JWT middleware was configured to handle tokens signed using RS256, but instead, a token was sent which was signed using HS256.
-
-
-
-The relevant error message to look for is the following:
-
-```
-IDX10503: Signature validation failed. Keys tried: 'null'.
-```
-
-
-
-
-
-
-In the case where you configured your middleware for HS256, but you are sending an RS256 signed token the error message will be different:
-
-
-
-In this case, the relevant error message to look for is the following:
-
-```
-IDX10500: Signature validation failed. Unable to resolve SecurityKeyIdentifier...
-```
-
-
-
-
-
-
-To resolve this issue, be sure that the signature algorithm with which the JWT was signed matches how your middleware is configured.
-
-## 3. Has your token expired?
-
-Each JSON Web Token is only valid until the time specified in the `exp` claim. If you and send a token which has expired, the token will be rejected:
-
-
-
-The error message to look for is the following:
-
-```
-Expired bearer token received
-```
-
-
-The resolve this issue, be sure to send a token which has not expired.
-
-### exp
-
-The value of the `exp` claim is a numeric value representing the number of seconds from 1970-01-01T00:00:00Z UTC until the specified UTC date/time. If you want to see the actual date/time for the value, you can visit [EpochConverter](http://www.epochconverter.com/).
-
-## 4. Did you configure the correct Issuer?
-
-The Issuer specified in your token must match exactly with what is configured in your JWT middleware.
-
-
-
-The error message to look for is the following:
-
-```
-IDX10205: Issuer validation failed.
-```
-
-
-The resolve this issue, ensure that you specify the correct issuer for your JWT middleware. If your middleware is configured for RS256 signed tokens, this means ensuring that you have specified the correct value for the `TokenValidationParameters.ValidIssuer` property of the `JwtBearerAuthenticationOptions` parameter passed when calling `app.UseJwtBearerAuthentication(...)`.
-
-If your middleware is configured for HS256 signed tokens, this means ensuring that you have passed the correct value to the constructor of `SymmetricKeyIssuerSecurityTokenProvider` which was configured as one of the `IssuerSecurityTokenProviders` for the `JwtBearerAuthenticationOptions`.
-
-## 5. Does the audience match?
-
-The audience specified in your token must match exactly with what is configured in your JWT middleware.
-
-
-
-The error message to look for is the following:
-
-```
-IDX10214: Audience validation failed.
-```
-
-
-The resolve this issue, ensure that you specify the correct audience for your JWT middleware. If your middleware is configured for RS256 signed tokens, this means ensuring that you have specified the correct value for the `ValidAudience` property of the `TokenValidationParameters`
-
-If your middleware is configured for HS256 signed tokens, this means ensuring that you have added the correct audience to the list of `AllowedAudiences` for the `JwtBearerAuthenticationOptions`.
-
-
-[Edit on GitHub](https://github.com/auth0/docs/edit/master/articles/quickstart/backend/webapi-owin/03-troubleshooting.md)
\ No newline at end of file
diff --git a/main/docs/quickstart/backend/webapi-owin/_index.mdx b/main/docs/quickstart/backend/webapi-owin/_index.mdx
deleted file mode 100644
index 4e8a0d15c..000000000
--- a/main/docs/quickstart/backend/webapi-owin/_index.mdx
+++ /dev/null
@@ -1,177 +0,0 @@
----
-title: Add Authorization to Your ASP.NET OWIN Web API Application
-sidebarTitle: ASP.NET Web API (OWIN)
-
----
-import { Recipe, Content, Section, SideMenu, SideMenuSectionItem, SignUpForm } from "/snippets/recipe.jsx";
-import { LoggedInForm } from "/snippets/Login.jsx";
-import Openidconnectsigningkeyresolver from "/snippets/quickstart/backend/webapi-owin/OpenIdConnectSigningKeyResolver.cs.mdx";
-import Scopeauthorizeattribute from "/snippets/quickstart/backend/webapi-owin/ScopeAuthorizeAttribute.cs.mdx";
-import Apicontroller from "/snippets/quickstart/backend/webapi-owin/ApiController.cs.mdx";
-
-import {AuthCodeGroup} from "/snippets/AuthCodeGroup.jsx";
-
-export const sections = [
- { id: "define-permissions", title: "Define permissions" },
- { id: "install-dependencies", title: "Install dependencies" },
- { id: "configure-the-middleware", title: "Configure the middleware" },
- { id: "verify-the-token-signature", title: "Verify the token signature" },
- { id: "validate-scopes", title: "Validate scopes" },
- { id: "protect-api-endpoints", title: "Protect API endpoints" }
-]
-
-
-
- Auth0 allows you to add authorization to any kind of application. This guide demonstrates how to integrate Auth0
- with any new or existing ASP.NET Owin Web API application using the `Microsoft.Owin.Security.Jwt`
- package.
-
- If you have not created an API in your Auth0 dashboard yet, you can use the interactive selector to create a new
- Auth0 API or select an existing API for your project.
-
- To set up your first API through the Auth0 dashboard, review our getting started guide.
-
- Each Auth0 API uses the API Identifier, which your application needs to validate the access token.
-
-
- **New to Auth0?** Learn how Auth0 works and
- read about implementing API authentication and
- authorization using the OAuth 2.0 framework.
-
-
-
- Permissions let you define how resources can be accessed on behalf of the user with a given access token. For
- example, you might choose to grant read access to the `messages` resource if users have the manager
- access level, and a write access to that resource if they have the administrator access level.
-
-
- You can define allowed permissions in the **Permissions** view of the Auth0 Dashboard's [APIs](https://manage.auth0.com/#/apis) section. The following
- example uses the `read:messages` scope.
-
-
-
-
-
-
-
-
-
- Install the `Microsoft.Owin.Security.Jwt` NuGetPackage. This package contains the OWIN JWT Middleware
- necessary to use Auth0 access tokens in the ASP.NET Owin Web API.
-
- ```ps lines
- Install-Package Microsoft.Owin.Security.Jwt
- ```
-
-
-
-
-
-
- Go to the `Configuration` method of your `Startup` class and add a call to
- `UseJwtBearerAuthentication` passing in the configured `JwtBearerAuthenticationOptions`.
-
- The `JwtBearerAuthenticationOptions` needs to specify your Auth0 API Identifier in the
- `ValidAudience` property, and the full path to your Auth0 domain as the `ValidIssuer`. You
- will need to configure the `IssuerSigningKeyResolver` to use the instance of
- `OpenIdConnectSigningKeyResolver` to resolve the signing key.
-
-
- **Do not forget the trailing slash.**
-
- Ensure the URL specified for `ValidIssuer` contains a trailing forward slash
- (`/`). This must match exactly with the JWT issuer claim. API calls will not authenticate
- correctly if you misconfigured this value.
-
-
-
-
-
-
-
-
-
-
-
- The OWIN JWT middleware does not use Open ID Connect Discovery by default, so you must provide a custom
- `IssuerSigningKeyResolver`.
-
- Create the `OpenIdConnectSigningKeyResolver` class and ensure to return the correct
- `SecurityKey` by implementing `GetSigningKey`. This class is then used as
- `TokenValidationParameters.IssuerSigningKeyResolver` while configuring the middleware in
- `Startup.cs`.
-
-
- This custom resolver is deprecated and [no longer available](https://github.com/auth0/auth0-aspnet-owin/blob/master/SECURITY-NOTICE.md). You must provide this custom resolver yourself.
-
-
-
-
-
-
-
-
-
-
- The JWT middleware verifies that the access token included in the request is valid; however, it doesn't yet
- include any mechanism for checking that the token has the sufficient **scope** to access the requested
- resources.
-
- Create a class called `ScopeAuthorizeAttribute` which inherits from
- `System.Web.Http.AuthorizeAttribute`. This attribute will check that the `scope` claim
- issued by your Auth0 tenant is present, and if so, it will ensure that the `scope` claim contains the
- requested scope.
-
-
-
-
-
-
-
-
-
- The routes shown below are available for the following requests:
-
- - `GET /api/public`: Available for non-authenticated requests.
- - `GET /api/private`: Available for authenticated requests containing an access token with no
- additional scopes.
- - `GET /api/private-scoped`: Available for authenticated requests containing an access token with
- the `read:messages`scope granted.
-
- The JWT middleware integrates with the standard ASP.NET authentication and authorization mechanisms, so you only
- need to decorate your controller action with the `[Authorize]` attribute to secure an endpoint.
-
- Update the action with the `ScopeAuthorize` attribute and pass the name of the required
- `scope` in the `scope` parameter. This ensures the correct scope is available to call a
- specific API endpoint.
-
-
- ##### Checkpoint
-
- Now that you have configured your application, run your application and verify that:
-
- - `GET /api/public`is available for non-authenticated requests.
- - `GET /api/private`is available for authenticated requests.
- - `GET /api/private-scoped`is available for authenticated requests containing an access
- token with the `read:messages`scope.
-
-
-
-
-
-
-
-
-
- ## Next Steps
-
- Excellent work! If you made it this far, you should now have login, logout, and user profile information running in your application.
-
- This concludes our quickstart tutorial, but there is so much more to explore. To learn more about what you can do with Auth0, check out:
-
- * [Auth0 Dashboard](https://manage.auth0.com/dashboard/us/dev-gja8kxz4ndtex3rq) - Learn how to configure and manage your Auth0 tenant and applications
- * [Auth0 Marketplace](https://marketplace.auth0.com/) - Discover integrations you can enable to extend Auth0’s functionality
-
-
-
-
diff --git a/main/docs/quickstart/backend/webapi-owin/index.mdx b/main/docs/quickstart/backend/webapi-owin/index.mdx
index 3e2b23acd..a7e3e7dc9 100644
--- a/main/docs/quickstart/backend/webapi-owin/index.mdx
+++ b/main/docs/quickstart/backend/webapi-owin/index.mdx
@@ -1,265 +1,245 @@
---
title: "ASP.NET Web API (OWIN): Authorization"
+description: "Add Auth0 JWT authorization to an ASP.NET OWIN API using the standard JWT middleware with protected endpoints"
---
-import {AuthCodeBlock} from "/snippets/AuthCodeBlock.jsx";
+import {AuthCodeGroup} from "/snippets/AuthCodeGroup.jsx";
-
-##### By Damien Guard
-
-This tutorial demonstrates how to add authorization to an ASP.NET OWIN API using the standard JWT middleware.We recommend that you log in to follow this quickstart with examples configured for your account.
{/*
System requirements: Microsoft Visual Studio 2015 Update 3 | System.IdentityModel.Tokens.Jwt NuGet Package v5.2.2 | Microsoft.Owin.Security.Jwt NuGet Package V4.0.0
*/}
-**New to Auth0?** Learn [how Auth0 works](/docs/get-started/auth0-overview) and read about [implementing API authentication and authorization](/docs/get-started/authentication-and-authorization-flow) using the OAuth 2.0 framework.
+ **New to Auth0?** Learn [how Auth0 works](/docs/get-started/auth0-overview) and read about [implementing API authentication and authorization](/docs/get-started/authentication-and-authorization-flow) using the OAuth 2.0 framework.
-## Configure Auth0 APIs
-
-### Create an API
-
-In the [APIs](https://manage.auth0.com/#/apis) section of the Auth0 dashboard, click **Create API**. Provide a name and an identifier for your API, for example, `https://quickstarts/api`. You will use the identifier as an `audience` later, when you are configuring the Access Token verification. Leave the **Signing Algorithm** as **RS256**.
-
-
-
-By default, your API uses RS256 as the algorithm for signing tokens. Since RS256 uses a private/public keypair, it verifies the tokens against the public key for your Auth0 account. The public key is in the [JSON Web Key Set (JWKS)](/docs/secure/tokens/json-web-tokens/json-web-key-sets) format, and can be accessed [here](https://{yourDomain}/.well-known/jwks.json).
-
-### Define permissions
+## Get Started
-Permissions let you define how resources can be accessed on behalf of the user with a given access token. For example, you might choose to grant read access to the `messages` resource if users have the manager access level, and a write access to that resource if they have the administrator access level.
-
-You can define allowed permissions in the **Permissions** view of the Auth0 Dashboard's [APIs](https://manage.auth0.com/#/apis) section.
-
-
-
-
-This example uses the `read:messages` scope.
-
+Auth0 allows you to add authorization to any kind of application. This guide demonstrates how to integrate Auth0 with any new or existing ASP.NET OWIN Web API application using the `Microsoft.Owin.Security.Jwt` package. Each Auth0 API uses the API Identifier, which your application needs to validate the access token.
This example demonstrates:
* How to check for a JSON Web Token (JWT) in the `Authorization` header of an incoming HTTP request.
* How to check if the token is valid, using the [JSON Web Key Set (JWKS)](/docs/secure/tokens/json-web-tokens/json-web-key-sets) for your Auth0 account. To learn more about validating Access Tokens, see [Validate Access Tokens](/docs/secure/tokens/access-tokens/validate-access-tokens).
-## Configure the Sample Project
-
-The sample code has an `appsettings` section in `Web.config` which configures it to use the correct Auth0 **Domain** and **API Identifier** for your API. If you download the code from this page it will be automatically filled. If you use the example from Github, you will need to fill it yourself.
-
-export const codeExample = `// web.config
-
-
-
-
-`;
-
-
-
-
-
-
-
-
-## Validate Access Tokens
-
-### Install dependencies
-
-To use Auth0 Access Tokens with ASP.NET you will use the OWIN JWT Middleware which is available in the `Microsoft.Owin.Security.Jwt` NuGet package.
-
-```bash lines
-Install-Package Microsoft.Owin.Security.Jwt
-```
-
-
-
-
-
-
-### Verifying the token signature
-
-As the OWIN JWT middleware doesn't use Open ID Connect Discovery by default, you will need to provide a custom `IssuerSigningKeyResolver`. To do this, add the following to the `Support/OpenIdConnectSigningKeyResolver.cs` file:
-
-
-Such a custom resolver was previously published as part of the `Auth0.OpenIdConnectSigningKeyResolver` package through Nuget. As [this package is not available anymore](https://github.com/auth0/auth0-aspnet-owin/blob/master/SECURITY-NOTICE.md), you will need to provide this yourself.
-
-
-```cs lines
-public class OpenIdConnectSigningKeyResolver
-{
- private readonly OpenIdConnectConfiguration openIdConfig;
-
- public OpenIdConnectSigningKeyResolver(string authority)
+
+
+ In the [APIs](https://manage.auth0.com/#/apis) section of the Auth0 dashboard, click **Create API**. Provide a name and an identifier for your API, for example, `https://quickstarts/api`. You will use the identifier as an `audience` later, when you are configuring the Access Token verification. Leave the **Signing Algorithm** as **RS256**.
+
+ 
+
+ By default, your API uses RS256 as the algorithm for signing tokens. Since RS256 uses a private/public keypair, it verifies the tokens against the public key for your Auth0 account. The public key is in the [JSON Web Key Set (JWKS)](/docs/secure/tokens/json-web-tokens/json-web-key-sets) format, and can be accessed [here](https://{yourDomain}/.well-known/jwks.json).
+
+
+ Permissions let you define how resources can be accessed on behalf of the user with a given access token. For example, you might choose to grant read access to the `messages` resource if users have the manager access level, and a write access to that resource if they have the administrator access level.
+
+ You can define allowed permissions in the **Permissions** view of the Auth0 Dashboard's [APIs](https://manage.auth0.com/#/apis) section.
+
+ 
+
+
+ This example uses the `read:messages` scope.
+
+
+
+ The sample code has an `appsettings` section in `Web.config` which configures it to use the correct Auth0 **Domain** and **API Identifier** for your API. If you download the code from this page it will be automatically filled. If you use the example from Github, you will need to fill it yourself.
+
+ ```xml web.config lines
+
+
+
+
+ ```
+
+
+ To use Auth0 Access Tokens with ASP.NET you will use the OWIN JWT Middleware which is available in the `Microsoft.Owin.Security.Jwt` NuGet package.
+
+ ```bash lines
+ Install-Package Microsoft.Owin.Security.Jwt
+ ```
+
+
+ As the OWIN JWT middleware doesn't use Open ID Connect Discovery by default, you will need to provide a custom `IssuerSigningKeyResolver`. To do this, add the following to the `Support/OpenIdConnectSigningKeyResolver.cs` file:
+
+
+ Such a custom resolver was previously published as part of the `Auth0.OpenIdConnectSigningKeyResolver` package through Nuget. As [this package is not available anymore](https://github.com/auth0/auth0-aspnet-owin/blob/master/SECURITY-NOTICE.md), you will need to provide this yourself.
+
+
+ ```cs OpenIdConnectSigningKeyResolver.cs lines
+ public class OpenIdConnectSigningKeyResolver
{
- var cm = new ConfigurationManager($"{authority.TrimEnd('/')}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
- openIdConfig = AsyncHelper.RunSync(async () => await cm.GetConfigurationAsync());
- }
-
- public SecurityKey[] GetSigningKey(string kid)
- {
- return new[] { openIdConfig.JsonWebKeySet.GetSigningKeys().FirstOrDefault(t => t.KeyId == kid) };
- }
-}
-```
-
-
-
-
-
-
-The `OpenIdConnectSigningKeyResolver` will automatically download the JSON Web Key Set used to sign the RS256 tokens from the OpenID Connect Configuration endpoint (at `/.well-known/openid-configuration`). You can then use it subsequently to resolve the Issuer Signing Key, as will be demonstrated in the JWT registration code below.
-
-### Configuration
-
-Go to the `Configuration` method of your `Startup` class and add a call to `UseJwtBearerAuthentication` passing in the configured `JwtBearerAuthenticationOptions`.
-
-The `JwtBearerAuthenticationOptions` needs to specify your Auth0 API Identifier in the `ValidAudience` property, and the full path to your Auth0 domain as the `ValidIssuer`. You will need to configure the `IssuerSigningKeyResolver` to use the instance of `OpenIdConnectSigningKeyResolver` to resolve the signing key:
+ private readonly OpenIdConnectConfiguration openIdConfig;
-```cs lines
-// Startup.cs
-
-public void Configuration(IAppBuilder app)
-{
- var domain = $"https://{ConfigurationManager.AppSettings["Auth0Domain"]}/";
- var apiIdentifier = ConfigurationManager.AppSettings["Auth0ApiIdentifier"];
- var keyResolver = new OpenIdConnectSigningKeyResolver(domain);
-
- app.UseJwtBearerAuthentication(
- new JwtBearerAuthenticationOptions
+ public OpenIdConnectSigningKeyResolver(string authority)
{
- AuthenticationMode = AuthenticationMode.Active,
- TokenValidationParameters = new TokenValidationParameters()
- {
- ValidAudience = apiIdentifier,
- ValidIssuer = domain,
- IssuerSigningKeyResolver = (token, securityToken, kid, parameters) => keyResolver.GetSigningKey(kid)
- }
- });
-
- // Configure Web API
- WebApiConfig.Configure(app);
-}
-```
-
-
-
-
+ var cm = new ConfigurationManager($"{authority.TrimEnd('/')}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
+ openIdConfig = AsyncHelper.RunSync(async () => await cm.GetConfigurationAsync());
+ }
-
-### Do not forget the trailing backslash
+ public SecurityKey[] GetSigningKey(string kid)
+ {
+ return new[] { openIdConfig.JsonWebKeySet.GetSigningKeys().FirstOrDefault(t => t.KeyId == kid) };
+ }
+ }
+ ```
-Please ensure that the URL specified for `ValidIssuer` contains a trailing backslash as this needs to match exactly with the issuer claim of the JWT. This is a common misconfiguration error which will cause your API calls to not be authenticated correctly.
-
+ The `OpenIdConnectSigningKeyResolver` will automatically download the JSON Web Key Set used to sign the RS256 tokens from the OpenID Connect Configuration endpoint (at `/.well-known/openid-configuration`). You can then use it subsequently to resolve the Issuer Signing Key, as will be demonstrated in the JWT registration code below.
+
+
+ Go to the `Configuration` method of your `Startup` class and add a call to `UseJwtBearerAuthentication` passing in the configured `JwtBearerAuthenticationOptions`.
-### Validate scopes
+ The `JwtBearerAuthenticationOptions` needs to specify your Auth0 API Identifier in the `ValidAudience` property, and the full path to your Auth0 domain as the `ValidIssuer`. You will need to configure the `IssuerSigningKeyResolver` to use the instance of `OpenIdConnectSigningKeyResolver` to resolve the signing key:
-The JWT middleware above verifies that the Access Token included in the request is valid; however, it doesn't yet include any mechanism for checking that the token has the sufficient **scope** to access the requested resources.
+ ```cs Startup.cs lines
+ public void Configuration(IAppBuilder app)
+ {
+ var domain = $"https://{ConfigurationManager.AppSettings["Auth0Domain"]}/";
+ var apiIdentifier = ConfigurationManager.AppSettings["Auth0ApiIdentifier"];
+ var keyResolver = new OpenIdConnectSigningKeyResolver(domain);
-Create a class called `ScopeAuthorizeAttribute` which inherits from `System.Web.Http.AuthorizeAttribute`. This Authorization Attribute will check that the `scope` claim issued by your Auth0 tenant is present, and if so it will ensure that the `scope` claim contains the requested scope.
+ app.UseJwtBearerAuthentication(
+ new JwtBearerAuthenticationOptions
+ {
+ AuthenticationMode = AuthenticationMode.Active,
+ TokenValidationParameters = new TokenValidationParameters()
+ {
+ ValidAudience = apiIdentifier,
+ ValidIssuer = domain,
+ IssuerSigningKeyResolver = (token, securityToken, kid, parameters) => keyResolver.GetSigningKey(kid)
+ }
+ });
+
+ // Configure Web API
+ WebApiConfig.Configure(app);
+ }
+ ```
-```cs lines
-// Controllers/ScopeAuthorizeAttribute.cs
+
+ ### Do not forget the trailing backslash
-public class ScopeAuthorizeAttribute : AuthorizeAttribute
-{
- private readonly string scope;
+ Please ensure that the URL specified for `ValidIssuer` contains a trailing backslash as this needs to match exactly with the issuer claim of the JWT. This is a common misconfiguration error which will cause your API calls to not be authenticated correctly.
+
+
+
+ The JWT middleware above verifies that the Access Token included in the request is valid; however, it doesn't yet include any mechanism for checking that the token has the sufficient **scope** to access the requested resources.
- public ScopeAuthorizeAttribute(string scope)
- {
- this.scope = scope;
- }
+ Create a class called `ScopeAuthorizeAttribute` which inherits from `System.Web.Http.AuthorizeAttribute`. This Authorization Attribute will check that the `scope` claim issued by your Auth0 tenant is present, and if so it will ensure that the `scope` claim contains the requested scope.
- public override void OnAuthorization(HttpActionContext actionContext)
+ ```cs ScopeAuthorizeAttribute.cs lines
+ public class ScopeAuthorizeAttribute : AuthorizeAttribute
{
- base.OnAuthorization(actionContext);
+ private readonly string scope;
- // Get the Auth0 domain, in order to validate the issuer
- var domain = $"https://{ConfigurationManager.AppSettings["Auth0Domain"]}/";
-
- // Get the claim principal
- ClaimsPrincipal principal = actionContext.ControllerContext.RequestContext.Principal as ClaimsPrincipal;
-
- // Get the scope claim. Ensure that the issuer is for the correct Auth0 domain
- var scopeClaim = principal?.Claims.FirstOrDefault(c => c.Type == "scope" && c.Issuer == domain);
- if (scopeClaim != null)
+ public ScopeAuthorizeAttribute(string scope)
{
- // Split scopes
- var scopes = scopeClaim.Value.Split(' ');
-
- // Succeed if the scope array contains the required scope
- if (scopes.Any(s => s == scope))
- return;
+ this.scope = scope;
}
- HandleUnauthorizedRequest(actionContext);
- }
-}
-```
-
-
-
+ public override void OnAuthorization(HttpActionContext actionContext)
+ {
+ base.OnAuthorization(actionContext);
+ // Get the Auth0 domain, in order to validate the issuer
+ var domain = $"https://{ConfigurationManager.AppSettings["Auth0Domain"]}/";
+ // Get the claim principal
+ ClaimsPrincipal principal = actionContext.ControllerContext.RequestContext.Principal as ClaimsPrincipal;
-## Protect API Endpoints
+ // Get the scope claim. Ensure that the issuer is for the correct Auth0 domain
+ var scopeClaim = principal?.Claims.FirstOrDefault(c => c.Type == "scope" && c.Issuer == domain);
+ if (scopeClaim != null)
+ {
+ // Split scopes
+ var scopes = scopeClaim.Value.Split(' ');
-The routes shown below are available for the following requests:
+ // Succeed if the scope array contains the required scope
+ if (scopes.Any(s => s == scope))
+ return;
+ }
-* `GET /api/public`: available for non-authenticated requests
-* `GET /api/private`: available for authenticated requests containing an access token with no additional scopes
-* `GET /api/private-scoped`: available for authenticated requests containing an access token with the `read:messages` scope granted
+ HandleUnauthorizedRequest(actionContext);
+ }
+ }
+ ```
+
+
+ The routes shown below are available for the following requests:
-The JWT middleware integrates with the standard ASP.NET Authentication and Authorization mechanisms, so you only need to decorate your controller action with the `[Authorize]` attribute to secure an endpoint.
+ * `GET /api/public`: available for non-authenticated requests
+ * `GET /api/private`: available for authenticated requests containing an access token with no additional scopes
+ * `GET /api/private-scoped`: available for authenticated requests containing an access token with the `read:messages` scope granted
-```cs lines
-// Controllers/ApiController.cs
+ The JWT middleware integrates with the standard ASP.NET Authentication and Authorization mechanisms, so you only need to decorate your controller action with the `[Authorize]` attribute to secure an endpoint. To ensure that a scope is present in order to call a particular API endpoint, decorate the action with the `ScopeAuthorize` attribute and pass the name of the required `scope` in the `scope` parameter.
-[RoutePrefix("api")]
-public class ApiController : ApiController
-{
- [HttpGet]
- [Route("private")]
- [Authorize]
- public IHttpActionResult Private()
+ ```cs ApiController.cs lines
+ [RoutePrefix("api")]
+ public class ApiController : ApiController
{
- return Json(new
+ [HttpGet]
+ [Route("public")]
+ public IHttpActionResult Public()
{
- Message = "Hello from a private endpoint! You need to be authenticated to see this."
- });
- }
-}
-```
-
-
-
-
-
-
-To ensure that a scope is present in order to call a particular API endpoint, you simply need to decorate the action with the `ScopeAuthorize` attribute and pass the name of the required `scope` in the `scope` parameter.
+ return Json(new
+ {
+ Message = "Hello from a public endpoint!"
+ });
+ }
-```cs lines
-// Controllers/ApiController.cs
+ [HttpGet]
+ [Route("private")]
+ [Authorize]
+ public IHttpActionResult Private()
+ {
+ return Json(new
+ {
+ Message = "Hello from a private endpoint! You need to be authenticated to see this."
+ });
+ }
-[RoutePrefix("api")]
-public class ApiController : ApiController
-{
- [HttpGet]
- [Route("private-scoped")]
- [ScopeAuthorize("read:messages")]
- public IHttpActionResult Scoped()
- {
- return Json(new
+ [HttpGet]
+ [Route("private-scoped")]
+ [ScopeAuthorize("read:messages")]
+ public IHttpActionResult Scoped()
{
- Message = "Hello from a private endpoint! You need to be authenticated and have a scope of read:messages to see this."
- });
+ return Json(new
+ {
+ Message = "Hello from a private endpoint! You need to be authenticated and have a scope of read:messages to see this."
+ });
+ }
}
-}
-```
-
-
-##### What can you do next?
-| [Configure other identity providers](/docs/authenticate/identity-providers) | [Enable multifactor authentication](/docs/secure/multi-factor-authentication) |
-| --- | --- |
-| [Learn about attack protection](/docs/secure/attack-protection) | [Learn about rules](/docs/customize/rules) |
-[Edit on GitHub](https://github.com/auth0/docs/edit/master/articles/quickstart/backend/aspnet-core-webapi/01-authorization.md)
-
----
\ No newline at end of file
+ ```
+
+
+
+
+ **Checkpoint**
+
+ Now that you have configured your application, run your application and verify that:
+
+ - `GET /api/public` is available for non-authenticated requests.
+ - `GET /api/private` is available for authenticated requests.
+ - `GET /api/private-scoped` is available for authenticated requests containing an access token with the `read:messages` scope.
+
+
+
+## Additional Resources
+
+
+
+ Complete sample application for this quickstart
+
+
+ Configure other identity providers
+
+
+ Enable multifactor authentication
+
+
+ Learn about attack protection
+
+
+ Extend Auth0 with custom logic
+
+
+ Get help from the Auth0 community
+
+
diff --git a/main/docs/quickstart/backend/webapi-owin/interactive.mdx b/main/docs/quickstart/backend/webapi-owin/interactive.mdx
deleted file mode 100644
index bd017d7cc..000000000
--- a/main/docs/quickstart/backend/webapi-owin/interactive.mdx
+++ /dev/null
@@ -1,195 +0,0 @@
----
-mode: wide
-description: This tutorial demonstrates how to add authorization to an ASP.NET OWIN API using the standard JWT middleware.
-sidebarTitle: ASP.NET Web API (OWIN)
-title: Add Authorization to Your ASP.NET OWIN Web API Application
----
-import { Recipe, Content, Section, SideMenu, SideMenuSectionItem, SignUpForm } from "/snippets/recipe.jsx";
-import { LoggedInForm } from "/snippets/Login.jsx";
-import Openidconnectsigningkeyresolver from "/snippets/quickstart/backend/webapi-owin/OpenIdConnectSigningKeyResolver.cs.mdx";
-import Scopeauthorizeattribute from "/snippets/quickstart/backend/webapi-owin/ScopeAuthorizeAttribute.cs.mdx";
-import Apicontroller from "/snippets/quickstart/backend/webapi-owin/ApiController.cs.mdx";
-
-import {QuickstartButtons} from "/snippets/QuickstartButtons.jsx";
-
-import {AuthCodeGroup} from "/snippets/AuthCodeGroup.jsx";
-
-
-
-export const sections = [
- { id: "define-permissions", title: "Define permissions" },
- { id: "install-dependencies", title: "Install dependencies" },
- { id: "configure-the-middleware", title: "Configure the middleware" },
- { id: "verify-the-token-signature", title: "Verify the token signature" },
- { id: "validate-scopes", title: "Validate scopes" },
- { id: "protect-api-endpoints", title: "Protect API endpoints" }
-]
-
-
-
- Auth0 allows you to add authorization to any kind of application. This guide demonstrates how to integrate Auth0
- with any new or existing ASP.NET Owin Web API application using the `Microsoft.Owin.Security.Jwt`
- package.
-
- If you have not created an API in your Auth0 dashboard yet, you can use the interactive selector to create a new
- Auth0 API or select an existing API for your project.
-
- To set up your first API through the Auth0 dashboard, review our getting started guide.
-
- Each Auth0 API uses the API Identifier, which your application needs to validate the access token.
-
-
- **New to Auth0?** Learn how Auth0 works and
- read about implementing API authentication and
- authorization using the OAuth 2.0 framework.
-
-
-
- Permissions let you define how resources can be accessed on behalf of the user with a given access token. For
- example, you might choose to grant read access to the `messages` resource if users have the manager
- access level, and a write access to that resource if they have the administrator access level.
-
-
- You can define allowed permissions in the **Permissions** view of the Auth0 Dashboard's [APIs](https://manage.auth0.com/#/apis) section. The following
- example uses the `read:messages` scope.
-
-
-
-
-
-
-
- Install the `Microsoft.Owin.Security.Jwt` NuGetPackage. This package contains the OWIN JWT Middleware
- necessary to use Auth0 access tokens in the ASP.NET Owin Web API.
-
- ```ps lines
- Install-Package Microsoft.Owin.Security.Jwt
- ```
-
-
-
-
- Go to the `Configuration` method of your `Startup` class and add a call to
- `UseJwtBearerAuthentication` passing in the configured `JwtBearerAuthenticationOptions`.
-
- The `JwtBearerAuthenticationOptions` needs to specify your Auth0 API Identifier in the
- `ValidAudience` property, and the full path to your Auth0 domain as the `ValidIssuer`. You
- will need to configure the `IssuerSigningKeyResolver` to use the instance of
- `OpenIdConnectSigningKeyResolver` to resolve the signing key.
-
-
- **Do not forget the trailing slash.**
-
- Ensure the URL specified for `ValidIssuer` contains a trailing forward slash
- (`/`). This must match exactly with the JWT issuer claim. API calls will not authenticate
- correctly if you misconfigured this value.
-
-
-
-
-
- The OWIN JWT middleware does not use Open ID Connect Discovery by default, so you must provide a custom
- `IssuerSigningKeyResolver`.
-
- Create the `OpenIdConnectSigningKeyResolver` class and ensure to return the correct
- `SecurityKey` by implementing `GetSigningKey`. This class is then used as
- `TokenValidationParameters.IssuerSigningKeyResolver` while configuring the middleware in
- `Startup.cs`.
-
-
- This custom resolver is deprecated and [no longer available](https://github.com/auth0/auth0-aspnet-owin/blob/master/SECURITY-NOTICE.md). You must provide this custom resolver yourself.
-
-
-
-
- The JWT middleware verifies that the access token included in the request is valid; however, it doesn't yet
- include any mechanism for checking that the token has the sufficient **scope** to access the requested
- resources.
-
- Create a class called `ScopeAuthorizeAttribute` which inherits from
- `System.Web.Http.AuthorizeAttribute`. This attribute will check that the `scope` claim
- issued by your Auth0 tenant is present, and if so, it will ensure that the `scope` claim contains the
- requested scope.
-
-
-
- The routes shown below are available for the following requests:
-
- - `GET /api/public`: Available for non-authenticated requests.
- - `GET /api/private`: Available for authenticated requests containing an access token with no
- additional scopes.
- - `GET /api/private-scoped`: Available for authenticated requests containing an access token with
- the `read:messages`scope granted.
-
- The JWT middleware integrates with the standard ASP.NET authentication and authorization mechanisms, so you only
- need to decorate your controller action with the `[Authorize]` attribute to secure an endpoint.
-
- Update the action with the `ScopeAuthorize` attribute and pass the name of the required
- `scope` in the `scope` parameter. This ensures the correct scope is available to call a
- specific API endpoint.
-
-
- ##### Checkpoint
-
- Now that you have configured your application, run your application and verify that:
-
- - `GET /api/public`is available for non-authenticated requests.
- - `GET /api/private`is available for authenticated requests.
- - `GET /api/private-scoped`is available for authenticated requests containing an access
- token with the `read:messages`scope.
-
-
-
- ## Next Steps
-
- Excellent work! If you made it this far, you should now have login, logout, and user profile information running in your application.
-
- This concludes our quickstart tutorial, but there is so much more to explore. To learn more about what you can do with Auth0, check out:
-
- * [Auth0 Dashboard](https://manage.auth0.com/dashboard/us/dev-gja8kxz4ndtex3rq) - Learn how to configure and manage your Auth0 tenant and applications
- * [Auth0 Marketplace](https://marketplace.auth0.com/) - Discover integrations you can enable to extend Auth0’s functionality
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-