diff --git a/SpotifyAPI.Docs/.prettierrc.json b/SpotifyAPI.Docs/.prettierrc.json
new file mode 100644
index 00000000..f1f48f70
--- /dev/null
+++ b/SpotifyAPI.Docs/.prettierrc.json
@@ -0,0 +1,8 @@
+{
+ "semi": true,
+ "trailingComma": "all",
+ "singleQuote": true,
+ "printWidth": 120,
+ "tabWidth": 2,
+ "endOfLine": "auto"
+}
diff --git a/SpotifyAPI.Docs/docs/auth_introduction.md b/SpotifyAPI.Docs/docs/auth_introduction.md
index 4652d7f4..dac18163 100644
--- a/SpotifyAPI.Docs/docs/auth_introduction.md
+++ b/SpotifyAPI.Docs/docs/auth_introduction.md
@@ -7,16 +7,17 @@ import useBaseUrl from '@docusaurus/useBaseUrl';
Spotify does not allow unauthorized access to the api. Thus, you need an access token to make requets. This access token can be gathered via multiple schemes, all following the OAuth2 spec. Since it's important to choose the correct scheme for your usecase, make sure you have a grasp of the following terminology/docs:
-* OAuth2
-* [Spotify Authorization Flows](https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow)
+- OAuth2
+- [Spotify Authorization Flows](https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow)
Since every auth flow also needs an application in the [spotify dashboard](https://developer.spotify.com/dashboard/), make sure you have the necessary values (like `Client Id` and `Client Secret`).
Then, continue with the docs of the specific auth flows:
-* [Client Credentials](client_credentials.md)
-* [Implicit Grant](implicit_grant.md)
-* [Authorization Code](authorization_code.md)
-* [Token Swap](token_swap.md)
+- [Client Credentials](client_credentials.md)
+- [Implicit Grant](implicit_grant.md)
+- [Authorization Code](authorization_code.md)
+- [PKCE](pkce.md)
+- [(Token Swap)](token_swap.md)
diff --git a/SpotifyAPI.Docs/docs/pkce.md b/SpotifyAPI.Docs/docs/pkce.md
new file mode 100644
index 00000000..206bafea
--- /dev/null
+++ b/SpotifyAPI.Docs/docs/pkce.md
@@ -0,0 +1,77 @@
+---
+id: pkce
+title: PKCE
+---
+
+> The authorization code flow with PKCE is the best option for mobile and desktop applications where it is unsafe to store your client secret. It provides your app with an access token that can be refreshed. For further information about this flow, see IETF RFC-7636.
+
+## Generating Challenge & Verifier
+
+For every authentation request, a verify code and its challenge code needs to be generated. The class `PKCEUtil` can be used to generate those, either with random generated or self supplied values:
+
+```csharp
+// Generates a secure random verifier of length 100 and its challenge
+var (verifier, challenge) = PKCEUtil.GenerateCodes();
+
+// Generates a secure random verifier of length 120 and its challenge
+var (verifier, challenge) = PKCEUtil.GenerateCodes(120);
+
+// Returns the passed string and its challenge (Make sure it's random and long enough)
+var (verifier, challenge) = PKCEUtil.GenerateCodes("YourSecureRandomString");
+```
+
+## Generating Login URI
+
+Like most auth flows, you'll need to redirect your user to spotify's servers so he is able to grant access to your application:
+
+```csharp
+// Make sure "http://localhost:5000/callback" is in your applications redirect URIs!
+var loginRequest = new LoginRequest(
+ new Uri("http://localhost:5000/callback"),
+ "YourClientId",
+ LoginRequest.ResponseType.Code
+)
+{
+ CodeChallengeMethod = "S256",
+ CodeChallenge = challenge,
+ Scope = new[] { Scopes.PlaylistReadPrivate, Scopes.PlaylistReadCollaborative }
+};
+var uri = loginRequest.ToUri();
+// Redirect user to uri via your favorite web-server or open a local browser window
+```
+
+When the user is redirected to the generated uri, he will have to login with his spotify account and confirm, that your application wants to access his user data. Once confirmed, he will be redirect to `http://localhost:5000/callback` and a `code` parameter is attached to the query. The redirect URI can also contain a custom protocol paired with UWP App Custom Protocol handler. This received `code` has to be exchanged for an `access_token` and `refresh_token`:
+
+```csharp
+// This method should be called from your web-server when the user visits "http://localhost:5000/callback"
+public Task GetCallback(string code)
+{
+ // Note that we use the verifier calculated above!
+ var initialResponse = await new OAuthClient().RequestToken(
+ new PKCETokenRequest("ClientId", code, "http://localhost:5000", verifier)
+ );
+
+ var spotify = new SpotifyClient(initialResponse.AccessToken);
+ // Also important for later: response.RefreshToken
+}
+```
+
+With PKCE you can also refresh tokens once they're expired:
+
+```csharp
+var newResponse = await new OAuthClient().RequestToken(
+ new PKCETokenRefreshRequest("ClientId", initialResponse.RefreshToken)
+);
+
+var spotify = new SpotifyClient(newResponse.AccessToken);
+```
+
+If you do not want to take care of manually refreshing tokens, you can use `PKCEAuthenticator`:
+
+```csharp
+var authenticator = new PKCEAuthenticator(clientId, initialResponse);
+
+var config = SpotifyClientConfig.CreateDefault()
+ .WithAuthenticator(authenticator);
+var spotify = new SpotifyClient(config);
+```
diff --git a/SpotifyAPI.Docs/package.json b/SpotifyAPI.Docs/package.json
index 3c1d3ae9..b06b5e68 100644
--- a/SpotifyAPI.Docs/package.json
+++ b/SpotifyAPI.Docs/package.json
@@ -8,6 +8,11 @@
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy"
},
+ "importSort": {
+ ".js, .jsx, .ts, .tsx": {
+ "style": "module"
+ }
+ },
"dependencies": {
"@docusaurus/core": "^2.0.0-alpha.56",
"@docusaurus/preset-classic": "^2.0.0-alpha.56",
@@ -27,5 +32,10 @@
"last 1 firefox version",
"last 1 safari version"
]
+ },
+ "devDependencies": {
+ "import-sort-style-module": "^6.0.0",
+ "prettier": "^2.0.5",
+ "prettier-plugin-import-sort": "^0.0.4"
}
}
diff --git a/SpotifyAPI.Docs/sidebars.js b/SpotifyAPI.Docs/sidebars.js
index 1eb3704f..2341d2fd 100644
--- a/SpotifyAPI.Docs/sidebars.js
+++ b/SpotifyAPI.Docs/sidebars.js
@@ -25,6 +25,7 @@ module.exports = {
'client_credentials',
'implicit_grant',
'authorization_code',
+ 'pkce',
'token_swap'
]
},
diff --git a/SpotifyAPI.Docs/src/install_instructions.js b/SpotifyAPI.Docs/src/install_instructions.js
index e31522f7..c91118a6 100644
--- a/SpotifyAPI.Docs/src/install_instructions.js
+++ b/SpotifyAPI.Docs/src/install_instructions.js
@@ -1,55 +1,55 @@
-import React from "react";
-import CodeBlock from '@theme/CodeBlock'
-import Tabs from '@theme/Tabs'
-import TabItem from '@theme/TabItem'
+import CodeBlock from '@theme/CodeBlock';
+import TabItem from '@theme/TabItem';
+import Tabs from '@theme/Tabs';
+import React from 'react';
// Will be removed after beta releases
const VERSION = '6.0.0-beta.9';
-const installCodeNuget =
- `Install-Package SpotifyAPI.Web -Version ${VERSION}
+const installCodeNuget = `Install-Package SpotifyAPI.Web -Version ${VERSION}
# Optional Auth module, which includes an embedded HTTP Server for OAuth2
Install-Package SpotifyAPI.Web.Auth -Version ${VERSION}
`;
-const installReference =
- `
+const installReference = `
`;
-const installCodeCLI =
- `dotnet add package SpotifyAPI.Web --version ${VERSION}
+const installCodeCLI = `dotnet add package SpotifyAPI.Web --version ${VERSION}
# Optional Auth module, which includes an embedded HTTP Server for OAuth2
dotnet add package SpotifyAPI.Web.Auth --version ${VERSION}
`;
const InstallInstructions = () => {
- return (
+ );
+};
export default InstallInstructions;
diff --git a/SpotifyAPI.Docs/src/pages/index.js b/SpotifyAPI.Docs/src/pages/index.js
index 538b37ba..3e15ffa7 100644
--- a/SpotifyAPI.Docs/src/pages/index.js
+++ b/SpotifyAPI.Docs/src/pages/index.js
@@ -1,18 +1,18 @@
-import React from 'react';
-import classnames from 'classnames';
-import Layout from '@theme/Layout';
-import CodeBlock from '@theme/CodeBlock'
-import Tabs from '@theme/Tabs'
-import TabItem from '@theme/TabItem'
import Link from '@docusaurus/Link';
-import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import useBaseUrl from '@docusaurus/useBaseUrl';
-import styles from './styles.module.css';
-import GitHubButton from 'react-github-btn'
-import InstallInstructions from '../install_instructions';
+import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
+import CodeBlock from '@theme/CodeBlock';
+import Layout from '@theme/Layout';
+import TabItem from '@theme/TabItem';
+import Tabs from '@theme/Tabs';
+import classnames from 'classnames';
+import React from 'react';
+import GitHubButton from 'react-github-btn';
-const exampleCode =
- `var spotify = new SpotifyClient("YourAccessToken");
+import InstallInstructions from '../install_instructions';
+import styles from './styles.module.css';
+
+const exampleCode = `var spotify = new SpotifyClient("YourAccessToken");
var me = await spotify.UserProfile.Current();
Console.WriteLine($"Hello there {me.DisplayName}");
@@ -30,7 +30,9 @@ const features = [
imageUrl: 'img/undraw_preferences_uuo2.svg',
description: () => (
<>
- SpotifyAPI-NET allows you to quickly integrate with Spotify's Web API by supplying sane configuration defaults from the start. Later on, behaviour can be customized using extensive configuration possibilities.
+ SpotifyAPI-NET allows you to quickly integrate with Spotify's Web API by supplying sane
+ configuration defaults from the start. Later on, behaviour can be customized using extensive configuration
+ possibilities.
>
),
},
@@ -39,7 +41,8 @@ const features = [
imageUrl: 'img/undraw_project_completed_w0oq.svg',
description: () => (
<>
- The Spotify Web API consists of over 74 API calls. SpotifyAPI-NET provides fully typed requests/responses for all of them.
+ The Spotify Web API consists of over 74 API calls. SpotifyAPI-NET provides fully typed
+ requests/responses for all of them.
>
),
},
@@ -48,7 +51,8 @@ const features = [
imageUrl: 'img/undraw_Devices_e67q.svg',
description: () => (
<>
- With the support of .NET Standard 2.X, SpotifyAPI-NET runs on many platforms, including .NET Core, UWP and Xamarin.Forms (Windows, Android, iOS and Mac)
+ With the support of .NET Standard 2.X, SpotifyAPI-NET runs on many platforms, including .NET Core,
+ UWP and Xamarin.Forms (Windows, Android, iOS and Mac)
>
),
},
@@ -57,7 +61,8 @@ const features = [
imageUrl: 'img/undraw_QA_engineers_dg5p.svg',
description: () => (
<>
- SpotifyAPI-NET is built on a modular structure, which allows easy testing through mocks and stubs. Learn more by visiting the Testing Guide
+ SpotifyAPI-NET is built on a modular structure, which allows easy testing through mocks and stubs.
+ Learn more by visiting the Testing Guide
>
),
},
@@ -82,9 +87,7 @@ function Home() {
const context = useDocusaurusContext();
const { siteConfig = {} } = context;
return (
-
+