From 8843d67a806d6f88095e5609884b3479e7f6432d Mon Sep 17 00:00:00 2001 From: Julien Calixte Date: Tue, 10 Mar 2026 12:27:35 +0100 Subject: [PATCH] feat: create atproto oauth login --- package.json | 1 + pnpm-lock.yaml | 234 ++++++++++++++++++ public/client-metadata.json | 15 ++ src/App.vue | 4 +- src/components/SignInAtproto.vue | 32 +++ src/components/WelcomeWorld.vue | 2 + src/data/DataType.enum.ts | 3 +- src/data/models/AtprotoSession.ts | 7 + src/hooks/useATProtoLogin.hook.ts | 59 +++++ src/hooks/useFollows.hook.ts | 21 ++ src/hooks/usePublicNoteList.hook.ts | 17 +- src/modules/atproto/service/atprotoOAuth.ts | 30 +++ src/modules/atproto/service/atprotoSession.ts | 23 ++ src/modules/atproto/service/getFollows.ts | 24 ++ src/views/PublicNoteListByDidView.vue | 2 +- src/views/PublicNoteListView.vue | 18 +- 16 files changed, 485 insertions(+), 7 deletions(-) create mode 100644 public/client-metadata.json create mode 100644 src/components/SignInAtproto.vue create mode 100644 src/data/models/AtprotoSession.ts create mode 100644 src/hooks/useATProtoLogin.hook.ts create mode 100644 src/hooks/useFollows.hook.ts create mode 100644 src/modules/atproto/service/atprotoOAuth.ts create mode 100644 src/modules/atproto/service/atprotoSession.ts create mode 100644 src/modules/atproto/service/getFollows.ts diff --git a/package.json b/package.json index 2597dc2..c24091b 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "generate-pwa-assets": "pwa-assets-generator" }, "dependencies": { + "@atproto/oauth-client-browser": "^0.3.41", "@better-fetch/fetch": "^1.1.21", "@better-fetch/logger": "^1.1.21", "@intlify/unplugin-vue-i18n": "^6.0.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7f7c7f7..6cb38a9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@atproto/oauth-client-browser': + specifier: ^0.3.41 + version: 0.3.41 '@better-fetch/fetch': specifier: ^1.1.21 version: 1.1.21 @@ -254,6 +257,66 @@ packages: '@ark/util@0.56.0': resolution: {integrity: sha512-BghfRC8b9pNs3vBoDJhcta0/c1J1rsoS1+HgVUreMFPdhz/CRAKReAu57YEllNaSy98rWAdY1gE+gFup7OXpgA==} + '@atproto-labs/did-resolver@0.2.6': + resolution: {integrity: sha512-2K1bC04nI2fmgNcvof+yA28IhGlpWn2JKYlPa7To9JTKI45FINCGkQSGiL2nyXlyzDJJ34fZ1aq6/IRFIOIiqg==} + + '@atproto-labs/fetch@0.2.3': + resolution: {integrity: sha512-NZtbJOCbxKUFRFKMpamT38PUQMY0hX0p7TG5AEYOPhZKZEP7dHZ1K2s1aB8MdVH0qxmqX7nQleNrrvLf09Zfdw==} + + '@atproto-labs/handle-resolver@0.3.6': + resolution: {integrity: sha512-qnSTXvOBNj1EHhp2qTWSX8MS5q3AwYU5LKlt5fBvSbCjgmTr2j0URHCv+ydrwO55KvsojIkTMgeMOh4YuY4fCA==} + + '@atproto-labs/identity-resolver@0.3.6': + resolution: {integrity: sha512-qoWqBDRobln0NR8L8dQjSp79E0chGkBhibEgxQa2f9WD+JbJdjQ0YvwwO5yeQn05pJoJmAwmI2wyJ45zjU7aWg==} + + '@atproto-labs/pipe@0.1.1': + resolution: {integrity: sha512-hdNw2oUs2B6BN1lp+32pF7cp8EMKuIN5Qok2Vvv/aOpG/3tNSJ9YkvfI0k6Zd188LeDDYRUpYpxcoFIcGH/FNg==} + + '@atproto-labs/simple-store-memory@0.1.4': + resolution: {integrity: sha512-3mKY4dP8I7yKPFj9VKpYyCRzGJOi5CEpOLPlRhoJyLmgs3J4RzDrjn323Oakjz2Aj2JzRU/AIvWRAZVhpYNJHw==} + + '@atproto-labs/simple-store@0.3.0': + resolution: {integrity: sha512-nOb6ONKBRJHRlukW1sVawUkBqReLlLx6hT35VS3imaNPwiXDxLnTK7lxw3Lrl9k5yugSBDQAkZAq3MPTEFSUBQ==} + + '@atproto/common-web@0.4.18': + resolution: {integrity: sha512-ilImzP+9N/mtse440kN60pGrEzG7wi4xsV13nGeLrS+Zocybc/ISOpKlbZM13o+twPJ+Q7veGLw9CtGg0GAFoQ==} + + '@atproto/did@0.3.0': + resolution: {integrity: sha512-raUPzUGegtW/6OxwCmM8bhZvuIMzxG5t9oWsth6Tp91Kb5fTnHV2h/KKNF1C82doeA4BdXCErTyg7ISwLbQkzA==} + + '@atproto/jwk-jose@0.1.11': + resolution: {integrity: sha512-i4Fnr2sTBYmMmHXl7NJh8GrCH+tDQEVWrcDMDnV5DjJfkgT17wIqvojIw9SNbSL4Uf0OtfEv6AgG0A+mgh8b5Q==} + + '@atproto/jwk-webcrypto@0.2.0': + resolution: {integrity: sha512-UmgRrrEAkWvxwhlwe30UmDOdTEFidlIzBC7C3cCbeJMcBN1x8B3KH+crXrsTqfWQBG58mXgt8wgSK3Kxs2LhFg==} + + '@atproto/jwk@0.6.0': + resolution: {integrity: sha512-bDoJPvt7TrQVi/rBfBrSSpGykhtIriKxeYCYQTiPRKFfyRhbgpElF0wPXADjIswnbzZdOwbY63az4E/CFVT3Tw==} + + '@atproto/lex-data@0.0.13': + resolution: {integrity: sha512-7Z7RwZ1Y/JzBF/Tcn/I4UJ/vIGfh5zn1zjv0KX+flke2JtgFkSE8uh2hOtqgBQMNqE3zdJFM+dcSWln86hR3MQ==} + + '@atproto/lex-json@0.0.13': + resolution: {integrity: sha512-hwLhkKaIHulGJpt0EfXAEWdrxqM2L1tV/tvilzhMp3QxPqYgXchFnrfVmLsyFDx6P6qkH1GsX/XC2V36U0UlPQ==} + + '@atproto/lexicon@0.6.2': + resolution: {integrity: sha512-p3Ly6hinVZW0ETuAXZMeUGwuMm3g8HvQMQ41yyEE6AL0hAkfeKFaZKos6BdBrr6CjkpbrDZqE8M+5+QOceysMw==} + + '@atproto/oauth-client-browser@0.3.41': + resolution: {integrity: sha512-4QTm8zPgm08vl53flrVmL+MS5IOhvWWctNZmEnPbvQ2t1ISw9Q5m815m2Sszi5ULMFjOqvT7lhKB7zQUn5gq5g==} + + '@atproto/oauth-client@0.6.0': + resolution: {integrity: sha512-F7ZTKzFptXgyihMkd7QTdRSkrh4XqrS+qTw+V81k5Q6Bh3MB1L3ypvfSJ6v7SSUJa6XxoZYJTCahHC1e+ndE6Q==} + + '@atproto/oauth-types@0.6.3': + resolution: {integrity: sha512-jdKuoPknJuh/WjI+mYk7agSbx9mNVMbS6Dr3k1z2YMY2oRiCQjxYBuo4MLKATbxj05nMQaZRWlHRUazoAu5Cng==} + + '@atproto/syntax@0.5.0': + resolution: {integrity: sha512-UA2DSpGdOQzUQ4gi5SH+NEJz/YR3a3Fg3y2oh+xETDSiTRmA4VhHRCojhXAVsBxUT6EnItw190C/KN+DWW90kw==} + + '@atproto/xrpc@0.7.7': + resolution: {integrity: sha512-K1ZyO/BU8JNtXX5dmPp7b5UrkLMMqpsIa/Lrj5D3Su+j1Xwq1m6QJ2XJ1AgjEjkI1v4Muzm7klianLE6XGxtmA==} + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -2653,6 +2716,9 @@ packages: resolution: {integrity: sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==} deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js. + core-js@3.48.0: + resolution: {integrity: sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==} + core-util-is@1.0.2: resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} @@ -4000,6 +4066,9 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + iso-datestring-validator@2.2.2: + resolution: {integrity: sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==} + isobject@2.1.0: resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} engines: {node: '>=0.10.0'} @@ -4119,6 +4188,9 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true + jose@5.10.0: + resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} + js-tokens@3.0.2: resolution: {integrity: sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==} @@ -4380,6 +4452,9 @@ packages: loupe@3.2.0: resolution: {integrity: sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw==} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} @@ -4530,6 +4605,9 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + multiformats@9.9.0: + resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} + nan@2.25.0: resolution: {integrity: sha512-0M90Ag7Xn5KMLLZ7zliPWP3rT90P6PN+IzVFS0VqmnPktBk3700xUVv8Ikm9EUaUE5SDWdp/BIxdENzVznpm1g==} @@ -5612,6 +5690,9 @@ packages: tslib@2.6.1: resolution: {integrity: sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsx@4.20.3: resolution: {integrity: sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==} engines: {node: '>=18.0.0'} @@ -5678,6 +5759,9 @@ packages: engines: {node: '>=0.8.0'} hasBin: true + uint8arrays@3.0.0: + resolution: {integrity: sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==} + unbox-primitive@1.1.0: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} @@ -5710,6 +5794,9 @@ packages: resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} engines: {node: '>=4'} + unicode-segmenter@0.14.5: + resolution: {integrity: sha512-jHGmj2LUuqDcX3hqY12Ql+uhUTn8huuxNZGq7GvtF6bSybzH3aFgedYu/KTzQStEgt1Ra2F3HxadNXsNjb3m3g==} + union-value@1.0.1: resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} engines: {node: '>=0.10.0'} @@ -6104,6 +6191,9 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + snapshots: '@aashutoshrathi/word-wrap@1.2.6': {} @@ -6130,6 +6220,130 @@ snapshots: '@ark/util@0.56.0': {} + '@atproto-labs/did-resolver@0.2.6': + dependencies: + '@atproto-labs/fetch': 0.2.3 + '@atproto-labs/pipe': 0.1.1 + '@atproto-labs/simple-store': 0.3.0 + '@atproto-labs/simple-store-memory': 0.1.4 + '@atproto/did': 0.3.0 + zod: 3.25.76 + + '@atproto-labs/fetch@0.2.3': + dependencies: + '@atproto-labs/pipe': 0.1.1 + + '@atproto-labs/handle-resolver@0.3.6': + dependencies: + '@atproto-labs/simple-store': 0.3.0 + '@atproto-labs/simple-store-memory': 0.1.4 + '@atproto/did': 0.3.0 + zod: 3.25.76 + + '@atproto-labs/identity-resolver@0.3.6': + dependencies: + '@atproto-labs/did-resolver': 0.2.6 + '@atproto-labs/handle-resolver': 0.3.6 + + '@atproto-labs/pipe@0.1.1': {} + + '@atproto-labs/simple-store-memory@0.1.4': + dependencies: + '@atproto-labs/simple-store': 0.3.0 + lru-cache: 10.4.3 + + '@atproto-labs/simple-store@0.3.0': {} + + '@atproto/common-web@0.4.18': + dependencies: + '@atproto/lex-data': 0.0.13 + '@atproto/lex-json': 0.0.13 + '@atproto/syntax': 0.5.0 + zod: 3.25.76 + + '@atproto/did@0.3.0': + dependencies: + zod: 3.25.76 + + '@atproto/jwk-jose@0.1.11': + dependencies: + '@atproto/jwk': 0.6.0 + jose: 5.10.0 + + '@atproto/jwk-webcrypto@0.2.0': + dependencies: + '@atproto/jwk': 0.6.0 + '@atproto/jwk-jose': 0.1.11 + zod: 3.25.76 + + '@atproto/jwk@0.6.0': + dependencies: + multiformats: 9.9.0 + zod: 3.25.76 + + '@atproto/lex-data@0.0.13': + dependencies: + multiformats: 9.9.0 + tslib: 2.8.1 + uint8arrays: 3.0.0 + unicode-segmenter: 0.14.5 + + '@atproto/lex-json@0.0.13': + dependencies: + '@atproto/lex-data': 0.0.13 + tslib: 2.8.1 + + '@atproto/lexicon@0.6.2': + dependencies: + '@atproto/common-web': 0.4.18 + '@atproto/syntax': 0.5.0 + iso-datestring-validator: 2.2.2 + multiformats: 9.9.0 + zod: 3.25.76 + + '@atproto/oauth-client-browser@0.3.41': + dependencies: + '@atproto-labs/did-resolver': 0.2.6 + '@atproto-labs/handle-resolver': 0.3.6 + '@atproto-labs/simple-store': 0.3.0 + '@atproto/did': 0.3.0 + '@atproto/jwk': 0.6.0 + '@atproto/jwk-webcrypto': 0.2.0 + '@atproto/oauth-client': 0.6.0 + '@atproto/oauth-types': 0.6.3 + core-js: 3.48.0 + + '@atproto/oauth-client@0.6.0': + dependencies: + '@atproto-labs/did-resolver': 0.2.6 + '@atproto-labs/fetch': 0.2.3 + '@atproto-labs/handle-resolver': 0.3.6 + '@atproto-labs/identity-resolver': 0.3.6 + '@atproto-labs/simple-store': 0.3.0 + '@atproto-labs/simple-store-memory': 0.1.4 + '@atproto/did': 0.3.0 + '@atproto/jwk': 0.6.0 + '@atproto/oauth-types': 0.6.3 + '@atproto/xrpc': 0.7.7 + core-js: 3.48.0 + multiformats: 9.9.0 + zod: 3.25.76 + + '@atproto/oauth-types@0.6.3': + dependencies: + '@atproto/did': 0.3.0 + '@atproto/jwk': 0.6.0 + zod: 3.25.76 + + '@atproto/syntax@0.5.0': + dependencies: + tslib: 2.8.1 + + '@atproto/xrpc@0.7.7': + dependencies: + '@atproto/lexicon': 0.6.2 + zod: 3.25.76 + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.27.1 @@ -8809,6 +9023,8 @@ snapshots: core-js@2.6.12: {} + core-js@3.48.0: {} + core-util-is@1.0.2: {} cose-base@1.0.3: @@ -10243,6 +10459,8 @@ snapshots: isexe@2.0.0: {} + iso-datestring-validator@2.2.2: {} + isobject@2.1.0: dependencies: isarray: 1.0.0 @@ -10518,6 +10736,8 @@ snapshots: jiti@2.6.1: {} + jose@5.10.0: {} + js-tokens@3.0.2: {} js-tokens@4.0.0: {} @@ -10762,6 +10982,8 @@ snapshots: loupe@3.2.0: {} + lru-cache@10.4.3: {} + lru-cache@4.1.5: dependencies: pseudomap: 1.0.2 @@ -10955,6 +11177,8 @@ snapshots: ms@2.1.3: {} + multiformats@9.9.0: {} + nan@2.25.0: optional: true @@ -12126,6 +12350,8 @@ snapshots: tslib@2.6.1: {} + tslib@2.8.1: {} + tsx@4.20.3: dependencies: esbuild: 0.25.5 @@ -12204,6 +12430,10 @@ snapshots: uglify-js@3.19.3: optional: true + uint8arrays@3.0.0: + dependencies: + multiformats: 9.9.0 + unbox-primitive@1.1.0: dependencies: call-bound: 1.0.4 @@ -12239,6 +12469,8 @@ snapshots: unicode-property-aliases-ecmascript@2.2.0: {} + unicode-segmenter@0.14.5: {} + union-value@1.0.1: dependencies: arr-union: 3.1.0 @@ -12727,3 +12959,5 @@ snapshots: yargs-parser: 7.0.0 yocto-queue@0.1.0: {} + + zod@3.25.76: {} diff --git a/public/client-metadata.json b/public/client-metadata.json new file mode 100644 index 0000000..671d3ab --- /dev/null +++ b/public/client-metadata.json @@ -0,0 +1,15 @@ +{ + "client_id": "https://remanso.space/client-metadata.json", + "client_name": "Remanso", + "client_uri": "https://remanso.space", + "redirect_uris": [ + "https://remanso.space/", + "http://localhost:5173/" + ], + "scope": "atproto transition:generic", + "grant_types": ["authorization_code", "refresh_token"], + "response_types": ["code"], + "application_type": "web", + "dpop_bound_access_tokens": true, + "token_endpoint_auth_method": "none" +} diff --git a/src/App.vue b/src/App.vue index bd96179..1f61b30 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,13 +1,15 @@