Added ErrorReceived to embedded auth server

Also style the default HTML site based on error/success values. Fixes #566
This commit is contained in:
Jonas Dellinger 2021-04-15 17:54:43 +02:00
parent ddb1dc0cc0
commit 163200f65c
6 changed files with 97 additions and 50 deletions

View File

@ -81,6 +81,7 @@ public static async Task Main()
await _server.Start(); await _server.Start();
_server.AuthorizationCodeReceived += OnAuthorizationCodeReceived; _server.AuthorizationCodeReceived += OnAuthorizationCodeReceived;
_server.ErrorReceived += OnErrorReceived;
var request = new LoginRequest(_server.BaseUri, "ClientId", LoginRequest.ResponseType.Code) var request = new LoginRequest(_server.BaseUri, "ClientId", LoginRequest.ResponseType.Code)
{ {
@ -103,6 +104,12 @@ private static async Task OnAuthorizationCodeReceived(object sender, Authorizati
var spotify = new SpotifyClient(tokenResponse.AccessToken); var spotify = new SpotifyClient(tokenResponse.AccessToken);
// do calls with Spotify and save token? // do calls with Spotify and save token?
} }
private static async Task OnErrorReceived(object sender, string error, string state)
{
Console.WriteLine($"Aborting authorization, error received: {error}");
await _server.Stop();
}
``` ```
For real examples, have a look at [Example.CLI.PersistentConfig](https://github.com/JohnnyCrazy/SpotifyAPI-NET/tree/master/SpotifyAPI.Web.Examples/Example.CLI.PersistentConfig) and [Example.CLI.CustomHTML](https://github.com/JohnnyCrazy/SpotifyAPI-NET/tree/master/SpotifyAPI.Web.Examples/Example.CLI.CustomHTML) For real examples, have a look at [Example.CLI.PersistentConfig](https://github.com/JohnnyCrazy/SpotifyAPI-NET/tree/master/SpotifyAPI.Web.Examples/Example.CLI.PersistentConfig) and [Example.CLI.CustomHTML](https://github.com/JohnnyCrazy/SpotifyAPI-NET/tree/master/SpotifyAPI.Web.Examples/Example.CLI.CustomHTML)

View File

@ -89,6 +89,7 @@ public static async Task Main()
await _server.Start(); await _server.Start();
_server.ImplictGrantReceived += OnImplicitGrantReceived; _server.ImplictGrantReceived += OnImplicitGrantReceived;
_server.ErrorReceived += OnErrorReceived;
var request = new LoginRequest(_server.BaseUri, "ClientId", LoginRequest.ResponseType.Token) var request = new LoginRequest(_server.BaseUri, "ClientId", LoginRequest.ResponseType.Token)
{ {
@ -103,6 +104,12 @@ private static async Task OnImplicitGrantReceived(object sender, ImplictGrantRes
var spotify = new SpotifyClient(response.AccessToken); var spotify = new SpotifyClient(response.AccessToken);
// do calls with Spotify // do calls with Spotify
} }
private static async Task OnErrorReceived(object sender, string error, string state)
{
Console.WriteLine($"Aborting authorization, error received: {error}");
await _server.Stop();
}
``` ```
For real examples, have a look at [Example.CLI.PersistentConfig](https://github.com/JohnnyCrazy/SpotifyAPI-NET/tree/master/SpotifyAPI.Web.Examples/Example.CLI.PersistentConfig) and [Example.CLI.CustomHTML](https://github.com/JohnnyCrazy/SpotifyAPI-NET/tree/master/SpotifyAPI.Web.Examples/Example.CLI.CustomHTML) For real examples, have a look at [Example.CLI.PersistentConfig](https://github.com/JohnnyCrazy/SpotifyAPI-NET/tree/master/SpotifyAPI.Web.Examples/Example.CLI.PersistentConfig) and [Example.CLI.CustomHTML](https://github.com/JohnnyCrazy/SpotifyAPI-NET/tree/master/SpotifyAPI.Web.Examples/Example.CLI.CustomHTML)

View File

@ -14,6 +14,7 @@ namespace SpotifyAPI.Web.Auth
{ {
public event Func<object, AuthorizationCodeResponse, Task>? AuthorizationCodeReceived; public event Func<object, AuthorizationCodeResponse, Task>? AuthorizationCodeReceived;
public event Func<object, ImplictGrantResponse, Task>? ImplictGrantReceived; public event Func<object, ImplictGrantResponse, Task>? ImplictGrantReceived;
public event Func<object, string, string?, Task>? ErrorReceived;
private const string AssetsResourcePath = "SpotifyAPI.Web.Auth.Resources.auth_assets"; private const string AssetsResourcePath = "SpotifyAPI.Web.Auth.Resources.auth_assets";
private const string DefaultResourcePath = "SpotifyAPI.Web.Auth.Resources.default_site"; private const string DefaultResourcePath = "SpotifyAPI.Web.Auth.Resources.default_site";
@ -38,6 +39,7 @@ namespace SpotifyAPI.Web.Auth
var error = query["error"]; var error = query["error"];
if (error != null) if (error != null)
{ {
ErrorReceived?.Invoke(this, error, query["state"]);
throw new AuthException(error, query["state"]); throw new AuthException(error, query["state"]);
} }

View File

@ -1,14 +1,14 @@
html, html,
body { body {
width : 100%; width: 100%;
height: 100%; height: 100%;
} }
body { body {
color : #f5f6fa; color: #f5f6fa;
background-color : #353b48; background-color: #353b48;
width : 100%; width: 100%;
height : 100%; height: 100%;
background-attachment: fixed; background-attachment: fixed;
} }
@ -20,3 +20,7 @@ main {
.logo { .logo {
margin-bottom: 50px; margin-bottom: 50px;
} }
.hidden {
visibility: hidden;
}

View File

@ -1,43 +1,54 @@
function getUrlParams(hash, start) { function getUrlParams(hash, start) {
const hashes = hash.slice(hash.indexOf(start) + 1).split('&') const hashes = hash.slice(hash.indexOf(start) + 1).split("&");
if (!hashes || hashes.length === 0 || hashes[0] === "") { if (!hashes || hashes.length === 0 || hashes[0] === "") {
return undefined; return undefined;
} }
const params = {} const params = {};
hashes.map(hash => { hashes.map((hash) => {
const [key, val] = hash.split('=') const [key, val] = hash.split("=");
params[key] = decodeURIComponent(val) params[key] = decodeURIComponent(val);
}) });
return params return params;
} }
function handleImplicitGrant() { function handleImplicitGrant() {
const params = getUrlParams(window.location.hash, '#'); const params = getUrlParams(window.location.hash, "#");
if (!params) { if (!params) {
return; return;
} }
params.request_type = "token"; params.request_type = "token";
console.log("Sent request_type token to server", params); console.log("Sent request_type token to server", params);
fetch('?' + new URLSearchParams(params).toString(), { fetch("?" + new URLSearchParams(params).toString(), {
method: 'POST', method: "POST",
}); });
} }
handleImplicitGrant(); handleImplicitGrant();
function handleAuthenticationCode() { function handleAuthenticationCode() {
const params = getUrlParams(window.location.search, '?'); const params = getUrlParams(window.location.search, "?");
if (!params) { if (!params) {
return; return;
} }
params.request_type = "code"; params.request_type = "code";
console.log("Sent request_type code to server", params); console.log("Sent request_type code to server", params);
fetch('?' + new URLSearchParams(params).toString(), { fetch("?" + new URLSearchParams(params).toString(), {
method: 'POST', method: "POST",
}); });
} }
handleAuthenticationCode(); handleAuthenticationCode();
document.addEventListener("DOMContentLoaded", () => {
const errorContainer = document.querySelector("#error");
const successContainer = document.querySelector("#success");
const params = new URLSearchParams(window.location.search);
if (params.has("error")) {
errorContainer.classList.remove("hidden");
} else {
successContainer.classList.remove("hidden");
}
});

View File

@ -1,38 +1,54 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Spotify Authorization</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css"
rel="stylesheet"
/>
<link href="/auth_assets/main.css" rel="stylesheet" />
<script src="/auth_assets/main.js"></script>
</head>
<head> <body>
<meta charset='utf-8'> <main>
<meta http-equiv='X-UA-Compatible' content='IE=edge'> <div class="flex justify-center flex-wrap logo">
<title>Spotify Authorization</title> <div class="w-1/8">
<meta name='viewport' content='width=device-width, initial-scale=1'> <img src="/auth_assets/logo.svg" width="120" height="120" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet"> </div>
<link href="/auth_assets/main.css" rel="stylesheet">
<script src="/auth_assets/main.js"></script>
</head>
<body>
<main>
<div class="flex justify-center flex-wrap logo">
<div class="w-1/8">
<img src="/auth_assets/logo.svg" width="120" height="120" />
</div> </div>
</div> <div id="error" class="hidden">
<h1 class="text-4xl">Success!</h1> <h1 class="text-4xl">Error!</h1>
<p class="text-xl mx-2"> <p class="text-xl mx-2">
Spotify Authorization was successful. You can close this tab and go back to your app. Spotify Authorization was not successful. You may want to retry.
</p> </p>
<div class="text-center py-4 lg:px-4 my-6">
<div class="p-2 bg-teal-800 items-center text-teal-100 leading-none lg:rounded-full flex lg:inline-flex"
role="alert">
<span class="flex rounded-full bg-teal-500 uppercase px-2 py-1 text-xs font-bold mr-3">Tip</span>
<span class="font-semibold mr-2 text-left flex-auto">
If the app does not detect the authorization, make sure you use one of the following supported Browsers:
<b>Chrome</b>, <b>Edge</b> or <b>Firefox</b>
</span>
</div> </div>
</div> <div id="success" class="hidden">
</main> <h1 class="text-4xl">Success!</h1>
</body> <p class="text-xl mx-2">
Spotify Authorization was successful. You can close this tab and go
back to your app.
</p>
</div>
<div class="text-center py-4 lg:px-4 my-6">
<div
class="p-2 bg-teal-800 items-center text-teal-100 leading-none lg:rounded-full flex lg:inline-flex"
role="alert"
>
<span
class="flex rounded-full bg-teal-500 uppercase px-2 py-1 text-xs font-bold mr-3"
>Tip</span
>
<span class="font-semibold mr-2 text-left flex-auto">
If the app does not detect the authorization, make sure you use one
of the following supported Browsers:
<b>Chrome</b>, <b>Edge</b> or <b>Firefox</b>
</span>
</div>
</div>
</main>
</body>
</html> </html>