This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch issue/oauth-oidc-spotify in repository https://gitbox.apache.org/repos/asf/sling-samples.git
commit d12e767ebbb607d4b60af9e0dc3218bf48309dec Author: Robert Munteanu <romb...@apache.org> AuthorDate: Mon Sep 1 17:11:01 2025 +0200 feat(oauth): login with Spotify --- oauth/README.md | 11 ++++++++++ oauth/launcher/Makefile | 7 +++++++ oauth/launcher/src/main/features/launcher.json | 21 ++++++++++++++++++- .../components/spotify-playlists/.content.xml | 22 ++++++++++++++++++++ .../spotify-playlists/spotify-playlists.html | 19 +++++++++++++++++ .../oauth-demo/components/welcome/welcome.html | 7 +++++-- .../content/oauth-demo/playlists/.content.xml | 24 ++++++++++++++++++++++ 7 files changed, 108 insertions(+), 3 deletions(-) diff --git a/oauth/README.md b/oauth/README.md index 23414d2..4c1c52c 100644 --- a/oauth/README.md +++ b/oauth/README.md @@ -54,6 +54,17 @@ Obtain the client id and client secret and save them under - `launcher/secrets/github/clientId` - `launcher/secrets/github/clientSecret` +### Spotify + +Create a new Spotify Developer app and generate client credentials for it. Follow the documentation from +https://developer.spotify.com/documentation/web-api . No special permissions are needed. + +Obtain the client id and client secret and save them under + +- `launcher/secrets/spotify/clientId` +- `launcher/secrets/spotify/clientSecret` + + ## Launching Change to the launcher directory and run `make run`. This will check if the required secrets are diff --git a/oauth/launcher/Makefile b/oauth/launcher/Makefile index eb1f716..633765b 100644 --- a/oauth/launcher/Makefile +++ b/oauth/launcher/Makefile @@ -28,6 +28,13 @@ secrets/github/clientId: secrets/github/clientSecret: @echo [WARN] $@ missing, OAuth config needs to be created manually +secrets/spotify/clientId: + @echo [WARN] $@ missing, OIDC config needs to be created manually + +secrets/spotify/clientSecret: + @echo [WARN] $@ missing, OIDC config needs to be created manually + + secrets/encrypt/password: mkdir -p secrets/encrypt openssl rand -hex 32 > $@ diff --git a/oauth/launcher/src/main/features/launcher.json b/oauth/launcher/src/main/features/launcher.json index a201ec6..bdb7215 100644 --- a/oauth/launcher/src/main/features/launcher.json +++ b/oauth/launcher/src/main/features/launcher.json @@ -27,8 +27,27 @@ "clientSecret": "$[secret:github/clientSecret]", "scopes": ["openid", "user:email"], "additionalAuthorizationParameters": ["prompt=select_account"] + }, + "org.apache.sling.auth.oauth_client.impl.OidcConnectionImpl~spotify": { + "name": "spotify", + "baseUrl": "https://accounts.spotify.com", + "clientId": "$[secret:spotify/clientId]", + "clientSecret": "$[secret:spotify/clientSecret]", + "scopes": ["openid"] }, - "org.apache.sling.auth.oauth_client.impl.JcrUserHomeOAuthTokenStore" : { + "org.apache.sling.auth.oauth_client.impl.OidcAuthenticationHandler": { + "path": "/content/oauth-demo/playlists", + "defaultConnectionName": "spotify", + "idp": "spotify-idp" + }, + "org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncHandler~spotify": { + "handler.name": "handler-spotify" + }, + "org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModuleFactory~spotify": { + "idp.name": "spotify-idp", + "sync.handlerName": "handler-spotify" + }, + "org.apache.sling.auth.oauth_client.impl.JcrUserHomeOAuthTokenStore": { }, "org.apache.sling.commons.crypto.internal.FilePasswordProvider~oauth": { "path": "secrets/encrypt/password", diff --git a/oauth/ui.apps/src/main/content/jcr_root/apps/oauth-demo/components/spotify-playlists/.content.xml b/oauth/ui.apps/src/main/content/jcr_root/apps/oauth-demo/components/spotify-playlists/.content.xml new file mode 100644 index 0000000..20e138a --- /dev/null +++ b/oauth/ui.apps/src/main/content/jcr_root/apps/oauth-demo/components/spotify-playlists/.content.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" + jcr:primaryType="sling:Folder" +/> diff --git a/oauth/ui.apps/src/main/content/jcr_root/apps/oauth-demo/components/spotify-playlists/spotify-playlists.html b/oauth/ui.apps/src/main/content/jcr_root/apps/oauth-demo/components/spotify-playlists/spotify-playlists.html new file mode 100644 index 0000000..0bbb6ea --- /dev/null +++ b/oauth/ui.apps/src/main/content/jcr_root/apps/oauth-demo/components/spotify-playlists/spotify-playlists.html @@ -0,0 +1,19 @@ +<!doctype html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link href="/oauth-demo/static/css/output.css" rel="stylesheet"> + <link rel="icon" href="/oauth-demo/static/favicon.ico"> + <title>Spotify Playlists</title> +</head> +<body data-sly-use.youtube="org.apache.sling.samples.oauth_demo.YoutubeVideosModel"> + <main> + <header class="flex flex-row justify-between"> + <h1>Spotify Playlists</h1> + </header> + <p>Not implemented.</p> + <p>Back to the <a class="underline" href="../oauth-demo.html">main page</a>.</p> + </main> +</body> +</html> \ No newline at end of file diff --git a/oauth/ui.apps/src/main/content/jcr_root/apps/oauth-demo/components/welcome/welcome.html b/oauth/ui.apps/src/main/content/jcr_root/apps/oauth-demo/components/welcome/welcome.html index d99b597..4636a05 100644 --- a/oauth/ui.apps/src/main/content/jcr_root/apps/oauth-demo/components/welcome/welcome.html +++ b/oauth/ui.apps/src/main/content/jcr_root/apps/oauth-demo/components/welcome/welcome.html @@ -17,17 +17,19 @@ <p>If you prefer, you can <a href="/system/sling/logout.html?resource=${resource.path}.html" class="underline">log out</a>.</p> </div> <div data-sly-test="${!user.loggedIn}"> - <p>Please <a href="/system/sling/login.html?resource=${resource.path}.html" class="underline">log in</a> to access the demo pages.</p> + <p>Access the <a class="underline" href="oauth-demo/playlists.html">Spotify playlists</a> page.</p> + <p>Please <a href="/system/sling/login.html?resource=${resource.path}.html" class="underline">log in</a> to access the other demo pages.</p> </div> </sly> <h2>About the demo</h2> <p>This application shows the expected basic usage of the <a class="underline" href="https://github.com/apache/sling-org-apache-sling-auth-oauth-client">Sling OAuth Client bundle</a></em></p> - <p>It exposes two pages: + <p>It exposes three pages: <ul class="list-disc list-inside"> <li>The Youtube videos page ( <a class="underline" href="https://github.com/apache/sling-samples/tree/master/oauth/ui.apps/src/main/content/jcr_root/apps/oauth-demo/components/youtube-videos">oauth-demo/components/youtube-videos</a>), implemented using a Sling Servlet ( <a class="underline" href="https://github.com/apache/sling-samples/blob/master/oauth/core/src/main/java/org/apache/sling/samples/oauth_demo/impl/YoutubeSearchServlet.java">YoutubeSearchServlet</a>) </li> <li>The GitHub repositories page ( <a class="underline" href="https://github.com/apache/sling-samples/tree/master/oauth/ui.apps/src/main/content/jcr_root/apps/oauth-demo/components/github-repos">oauth-demo/components/github-repos</a>), backed by a Sling Model ( <a class="underline" href="https://github.com/apache/sling-samples/blob/master/oauth/core/src/main/java/org/apache/sling/samples/oauth_demo/GithubRepositoriesModel.java">GithubRepositoriesModel</a>) </li> + <li>The Spotify playlists page ( <a class="underline" href="https://github.com/apache/sling-samples/tree/master/oauth/ui.apps/src/main/content/jcr_root/apps/oauth-demo/components/spotify-playlists">oauth-demo/components/spotify-playlists</a>), implemented using a TODO</li> </ul> </p> @@ -35,6 +37,7 @@ <ul class="list-disc list-inside"> <li>Google: <a target="_blank" class="underline" href="https://developers.google.com/identity/protocols/oauth2">Using OAuth 2.0 to Access Google APIs </a></li> <li>GitHub: <a target="_blank" class="underline" href="https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps">Authorizing OAuth Apps</a></li> + <li>Spotify: <a target="_blank" class="underline" href="https://developer.spotify.com/documentation/web-api/tutorials/getting-started">Getting started with Web API</a></li> </ul> </p> diff --git a/oauth/ui.apps/src/main/content/jcr_root/content/oauth-demo/playlists/.content.xml b/oauth/ui.apps/src/main/content/jcr_root/content/oauth-demo/playlists/.content.xml new file mode 100644 index 0000000..fc54601 --- /dev/null +++ b/oauth/ui.apps/src/main/content/jcr_root/content/oauth-demo/playlists/.content.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" + xmlns:sling="http://sling.apache.org/jcr/sling/1.0" + jcr:primaryType="sling:Folder" + sling:resourceType="oauth-demo/components/spotify-playlists" +/> \ No newline at end of file