{"_id":"@bluesky-social/oauth-client-expo","name":"@bluesky-social/oauth-client-expo","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"@bluesky-social/oauth-client-expo","version":"0.0.1","license":"MIT","description":"ATPROTO OAuth client for Expo applications","authors":["Hailey <me@haileyok.com> (https://github.com/haileyok)","Matthieu Sieben <me@matthieusieben.com> (https://github.com/matthieusieben)"],"keywords":["atproto","oauth","client","react-native","expo"],"bugs":{"url":"https://github.com/bluesky-social/atproto/issues"},"homepage":"https://github.com/bluesky-social/atproto/tree/main/packages/oauth/oauth-client-expo#readme","repository":{"type":"git","url":"git+https://github.com/bluesky-social/atproto.git","directory":"packages/oauth/oauth-client-expo"},"main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"dependencies":{"abortcontroller-polyfill":"^1.7.8","core-js":"^3.46.0","event-target-polyfill":"^0.0.4","expo-web-browser":"^15.0.8","react-native-mmkv":"^3.3.3","react-native-url-polyfill":"^3.0.0","@bluesky-social/oauth-client":"0.5.7","@bluesky-social/oauth-client-browser":"0.3.33","@atproto-labs/simple-store":"0.3.0"},"peerDependencies":{"expo":"*","react-native":"*"},"scripts":{"build":"tsc --build tsconfig.build.json"},"_id":"@bluesky-social/oauth-client-expo@0.0.1","_integrity":"sha512-Nb43DLvN0bkV2FBo2f4emPTJHSNIvcujL4z0v36sKPLsnrWI5YojQGBymrhibsFipvMlI2BeOcggGOvfwH1IZQ==","_resolved":"/private/var/folders/cb/7sst87dj7jd40nc7b7q7h76r0000gn/T/8a63a459840af00c5103c31d365a4b92/bluesky-social-oauth-client-expo-0.0.1.tgz","_from":"file:bluesky-social-oauth-client-expo-0.0.1.tgz","_nodeVersion":"20.15.0","_npmVersion":"10.7.0","dist":{"integrity":"sha512-Nb43DLvN0bkV2FBo2f4emPTJHSNIvcujL4z0v36sKPLsnrWI5YojQGBymrhibsFipvMlI2BeOcggGOvfwH1IZQ==","shasum":"886e44a0100b1526bc8248722adb347ae986ca52","tarball":"https://registry.npmjs.org/@bluesky-social/oauth-client-expo/-/oauth-client-expo-0.0.1.tgz","fileCount":81,"unpackedSize":96833,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFsT0lSlknYjoxlJvOksi4cHTxUVRzLxg6EP8OUjo7zwAiBY8IsdZLChV3hWqaVbbspelhH8bnqX3BWwFNO78aDn8g=="}]},"_npmUser":{"name":"web3km","email":"web3km@proton.me"},"directories":{},"maintainers":[{"name":"openweb3.io","email":"mtsocialdao@gmail.com"},{"name":"web3km","email":"web3km@proton.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/oauth-client-expo_0.0.1_1761039229260_0.1807450752170272"},"_hasShrinkwrap":false}},"time":{"created":"2025-10-21T09:33:49.187Z","0.0.1":"2025-10-21T09:33:49.433Z","modified":"2025-10-21T09:33:49.706Z"},"maintainers":[{"name":"openweb3.io","email":"mtsocialdao@gmail.com"},{"name":"web3km","email":"web3km@proton.me"}],"description":"ATPROTO OAuth client for Expo applications","homepage":"https://github.com/bluesky-social/atproto/tree/main/packages/oauth/oauth-client-expo#readme","keywords":["atproto","oauth","client","react-native","expo"],"repository":{"type":"git","url":"git+https://github.com/bluesky-social/atproto.git","directory":"packages/oauth/oauth-client-expo"},"bugs":{"url":"https://github.com/bluesky-social/atproto/issues"},"license":"MIT","readme":"# Expo Atproto OAuth\n\nThis is an Expo client library for Atproto OAuth. It implements the required\nnative crypto functions for supporting JWTs in React Native and uses the base\n`OAuthClient` interface found in [the Atproto repository](https://github.com/bluesky-social/atproto/tree/main/packages/oauth/oauth-client).\n\n### In bare React Native projects\n\nFor bare React Native projects, you must ensure that you have [installed and configured the `expo` package](https://docs.expo.dev/bare/installing-expo-modules/)\nbefore continuing.\n\n## Installation\n\nOnce you have satisfied the prerequisites, you can simply install the library with `npm install --save @bluesky-social/oauth-client-expo`.\n\n## Usage\n\n### Serve your `oauth-client-metadata.json`\n\nYou will need to server an `oauth-client-metadata.json` from your application's website. An example of this metadata\nwould look like this:\n\n```json\n// assets/oauth-client-metadata.json\n{\n  \"client_id\": \"https://example.com/oauth-client-metadata.json\",\n  \"client_name\": \"React Native OAuth Client Demo\",\n  \"client_uri\": \"https://example.com\",\n  \"redirect_uris\": [\"com.example:/auth/callback\"],\n  \"scope\": \"atproto repo:* rpc:*?aud=did:web:api.bsky.app#bsky_appview\",\n  \"token_endpoint_auth_method\": \"none\",\n  \"response_types\": [\"code\"],\n  \"grant_types\": [\"authorization_code\", \"refresh_token\"],\n  \"application_type\": \"native\",\n  \"dpop_bound_access_tokens\": true\n}\n```\n\n- The `client_id` should be the same URL as where you are serving your\n  `oauth-client-metadata.json` from\n- The `client_uri` can be the home page of where you are serving your metadata\n  from\n- Your `redirect_uris` should contain a native redirect URI (for ios/android),\n  as well as a web redirect URI (for web).\n- native redirect URI must have a custom scheme, which is formatted as the\n  _reverse_ of the domain you are serving the metadata from. Since I am serving\n  mine from `example.com`, I use `com.example` as the scheme. If my domain were\n  `atproto.expo.dev`, I would use `dev.expo.atproto`. Additionally, the scheme\n  _must_ contain _only one trailing slash_ after the `:`. `com.example://` is\n  invalid.\n- The `application_type` must be `native`\n\nFor a real-world example, see [Skylight's client metadata](https://skylight.expo.app/oauth/client-metadata.json).\n\nFor more information about client metadata, see [the Atproto documentation](https://atproto.com/specs/oauth#client-id-metadata-document).\n\n### Create a client\n\nNext, you want to create an `ExpoOAuthClient`. You will need to pass in the same client metadata to the client as you are serving in your `oauth-client-metadata.json`.\n\n```ts\n// utils/oauth-client.ts\nconst clientMetadata = require('../assets/oauth-client-metadata.json')\n\nconst client = new ExpoOAuthClient({\n  handleResolver: 'https://bsky.social',\n  clientMetadata,\n})\n```\n\n### Sign a user in\n\nWhenever you are ready, you can initiate a sign in attempt for the user using the client using `client.signIn(input)`\n\n`input` must be one of the following:\n\n- A valid Atproto user handle, e.g. `hailey.bsky.team` or `example.com`\n- A valid DID, e.g. `did:web:example.com` or `did:plc:oisofpd7lj26yvgiivf3lxsi`\n- A valid PDS host, e.g. `https://cocoon.example.com` or `https://bsky.social`\n\n> [!NOTE] If you wish to allow a user to _create_ an account instead of signing\n> in, simply use a valid PDS hostname rather than a handle. They will be\n> presented the option to either Sign In with an existing account, or create a\n> new one, on the PDS's sign in page.\n\nThe response of `signIn` will be a promise resolving to the following:\n\n```ts\n    | { status: WebBrowserResultType } // See Expo Web Browser documentation\n    | { status: 'error'; error: unknown }\n    | { status: 'success'; session: OAuthSession }\n```\n\nFor example:\n\n```ts\ntry {\n  const session = await client.signIn(input ?? '')\n  setSession(session)\n  const agent = new Agent(session)\n  setAgent(agent)\n} catch (err) {\n  Alert.alert('Error', String(err))\n}\n```\n\n### Create an `Agent`\n\nTo interface with the various Atproto APIs, you will need to create an `Agent`. You will pass your `OAuthSession` to the `Agent` or `XrpcClient` constructor.\n\n```ts\nconst agent = new Agent(session)\n// or\nconst xrpc = new XrpcClient(session)\n```\n\nSession refreshes will be handled for you for the lifetime of the agent.\n\n### Restoring a session\n\nAfter, for example, closing the application, you will probably need to restore the user's session. You can do this by using the user's DID on the `ExpoOAuthClient`.\n\n```ts\nconst session = await client.restore('did:plc:oisofpd7lj26yvgiivf3lxsi')\nconst agent = new Agent(session)\n```\n\nIf the session needs to be refreshed, `.restore()` will automatically do this for you before returning a session (based on the token's expiration date). In order to force a refresh, you can pass in `true` as the second argument to `restore`.\n\n```ts\nconst session = await client.restore(\n  'did:plc:oisofpd7lj26yvgiivf3lxsi',\n  true, // force a refresh, ensuring tokens were not revoked\n)\n```\n\n## Additional Reading\n\n- [Atproto OAuth Spec](https://atproto.com/specs/oauth)\n- [Atproto Web OAuth Example](https://github.com/bluesky-social/atproto/tree/main/packages/oauth/oauth-client-browser-example)\n","readmeFilename":"README.md","_rev":"1-2048d9db57d1c4f3923db3e10049c6b7"}