|
| 1 | +<!doctype html> |
| 2 | +<html lang="en"> |
| 3 | +<head> |
| 4 | +<meta charset="utf-8"> |
| 5 | +<meta name="viewport" content="width=device-width,initial-scale=1"> |
| 6 | +<title>Sign in — Solid pod</title> |
| 7 | +<style> |
| 8 | +body{font:14px/1.6 system-ui,-apple-system,sans-serif;color:#222;background:#f3eee5;max-width:560px;margin:2em auto;padding:0 1em} |
| 9 | +.card{background:#fff;border-radius:12px;box-shadow:0 2px 12px rgba(0,0,0,.08);padding:1.5em 2em} |
| 10 | +h1{margin:0 0 .5em;font-weight:500;font-size:1.6em} |
| 11 | +.lede{color:#555;margin:0 0 1em} |
| 12 | +.creds{background:#f3eee5;padding:.8em 1em;border-radius:8px;margin:1em 0;font-family:"SFMono-Regular",Consolas,monospace} |
| 13 | +.creds .label{font-family:system-ui,sans-serif;color:#555;margin-right:.5em} |
| 14 | +.error{background:#fff0f0;color:#a00;padding:.8em 1em;border-radius:8px;margin:1em 0;display:none;font-family:"SFMono-Regular",Consolas,monospace;font-size:.9em;word-break:break-word} |
| 15 | +.error.show{display:block} |
| 16 | +a{color:#0a66c2;text-decoration:none} |
| 17 | +a:hover{text-decoration:underline} |
| 18 | +.btn{display:inline-block;padding:.6em 1.2em;border-radius:6px;text-decoration:none;font-size:.95em;background:#0a66c2;color:#fff;border:1px solid transparent;cursor:pointer} |
| 19 | +.btn:hover{background:#084e96;text-decoration:none} |
| 20 | +.btn-secondary{background:#fff;color:#222;border-color:#ddd} |
| 21 | +.btn-secondary:hover{background:#f0efeb} |
| 22 | +footer{margin-top:1.5em;padding-top:1em;border-top:1px solid #eee;color:#888;font-size:.85em;text-align:center} |
| 23 | +</style> |
| 24 | +</head> |
| 25 | +<body> |
| 26 | +<div class="card"> |
| 27 | +<h1 id="title">Signing in…</h1> |
| 28 | +<p class="lede" id="lede">Starting Solid-OIDC handshake with <strong id="pod-url">this pod</strong>.</p> |
| 29 | +<div class="creds"> |
| 30 | +<span class="label">Default sign-in:</span> me <span class="label">/</span> me |
| 31 | +</div> |
| 32 | +<div class="error" id="error"></div> |
| 33 | +<p id="retry" style="display:none"><a href="./signin.html" class="btn">Try again</a> <a href="./" class="btn btn-secondary">Back to pod</a></p> |
| 34 | +<footer>Powered by <a href="https://github.com/JavaScriptSolidServer/jspod">jspod</a> · <a href="https://github.com/JavaScriptSolidServer/solid-oidc">solid-oidc</a></footer> |
| 35 | +</div> |
| 36 | +<script type="module"> |
| 37 | +// Tiny sign-in client. Uses solid-oidc (zero-dep, AGPL, same org). |
| 38 | +// Flow: |
| 39 | +// 1. Fresh visit → try restore; if active, redirect to /. Else call |
| 40 | +// session.login(idp, redirectUri) which bounces to /idp with OAuth |
| 41 | +// params; JSS renders its real login form there. |
| 42 | +// 2. Return visit (?code= present) → handleRedirectFromLogin, then |
| 43 | +// redirect home. |
| 44 | +import Session from 'https://cdn.jsdelivr.net/npm/solid-oidc@0.0.8/solid-oidc.js'; |
| 45 | + |
| 46 | +const idp = new URL('./', window.location.href).href; |
| 47 | +const redirectUri = new URL('./signin.html', window.location.href).href; |
| 48 | + |
| 49 | +document.getElementById('pod-url').textContent = idp; |
| 50 | + |
| 51 | +const titleEl = document.getElementById('title'); |
| 52 | +const ledeEl = document.getElementById('lede'); |
| 53 | +const errorEl = document.getElementById('error'); |
| 54 | +const retryEl = document.getElementById('retry'); |
| 55 | + |
| 56 | +function fail(msg) { |
| 57 | + titleEl.textContent = 'Sign-in failed'; |
| 58 | + ledeEl.style.display = 'none'; |
| 59 | + errorEl.textContent = msg; |
| 60 | + errorEl.classList.add('show'); |
| 61 | + retryEl.style.display = 'block'; |
| 62 | +} |
| 63 | + |
| 64 | +try { |
| 65 | + const session = new Session(); |
| 66 | + const params = new URLSearchParams(window.location.search); |
| 67 | + |
| 68 | + if (params.get('code')) { |
| 69 | + titleEl.textContent = 'Completing sign-in…'; |
| 70 | + ledeEl.textContent = 'Exchanging the authorization code for a token.'; |
| 71 | + await session.handleRedirectFromLogin(); |
| 72 | + titleEl.textContent = 'Signed in'; |
| 73 | + ledeEl.textContent = 'WebID: ' + (session.webId || '(none)') + '. Redirecting…'; |
| 74 | + setTimeout(() => { window.location.href = './'; }, 800); |
| 75 | + } else { |
| 76 | + // Try to restore a prior session. solid-oidc throws "Missing |
| 77 | + // refresh data" on a clean first visit — that's fine, it just |
| 78 | + // means there's no session yet and we should kick off login. |
| 79 | + let restored = false; |
| 80 | + try { |
| 81 | + await session.restore(); |
| 82 | + restored = session.isActive; |
| 83 | + } catch { |
| 84 | + restored = false; |
| 85 | + } |
| 86 | + if (restored) { |
| 87 | + titleEl.textContent = 'Already signed in'; |
| 88 | + ledeEl.textContent = 'WebID: ' + session.webId + '. Redirecting…'; |
| 89 | + setTimeout(() => { window.location.href = './'; }, 400); |
| 90 | + } else { |
| 91 | + await session.login(idp, redirectUri); |
| 92 | + } |
| 93 | + } |
| 94 | +} catch (e) { |
| 95 | + fail(e && e.message ? e.message : String(e)); |
| 96 | +} |
| 97 | +</script> |
| 98 | +</body> |
| 99 | +</html> |
0 commit comments