Signing in

Your password is only ever typed into your browser. Every check made on both sides.

Opensolr Photos signs in the way RFC 8252 says native apps should: the OAuth 2.0 authorization code flow with PKCE, with the login page in your phone's real browser. Your password is only ever typed there.

The app holds the verifier Browser Custom Tab opensolr.com /app/* 1 · open /app/authorize code_challenge (S256), state 2 · GET /app/authorize 3 · 303 to the login when signed out 4 · login, reCAPTCHA, two-factor 5 · approval page, cannot be framed 6 · POST Allow, with CSRF token 7 · 303 /app/callback?code&state one-time code, valid 60 seconds 8 · verified App Link opens the app 9 · POST /app/token code + code_verifier + state checked in the app 10 · email, API key, plan limits The password is only ever typed into the browser. Without the verifier, a code seen by anyone else is worthless.

Figure 1 — the sign-in sequence between the app, the browser and opensolr.com.

01 · Why the browser, not a screen inside the app
  • The login opens in a Chrome Custom Tab, never in a WebView embedded in the app, so the app cannot see or read anything typed on that page.
  • Your browser's saved passwords and an existing opensolr.com session work. Already signed in to opensolr.com in the browser? There is nothing to type.
  • It is the normal Opensolr login, with everything it already carries: reCAPTCHA, the per-address attempt limit, the account lockout, and two-factor authentication.
02 · Step by step
  1. The app prepares. It generates a random code_verifier (48 random bytes) and a random state (24 random bytes), stores both, and sends only code_challenge = base64url(SHA-256(code_verifier)).
  2. The browser opens /app/authorize with client_id=opensolr-photos, redirect_uri=https://opensolr.com/app/callback, the challenge, S256, the state and a device label such as Google Pixel 8.
  3. opensolr.com checks the request. The client and the redirect address must equal fixed values exactly, the challenge and the state must have the right shape. Anything else gets an error page, never a redirect. The valid request is remembered for 15 minutes.
  4. Login, if the browser is not signed in yet, including two-factor.
  5. The approval page names the signed-in account, the phone asking, and exactly what the app will do. It cannot be placed inside a frame, so it cannot be clicked on your behalf, and it is never cached.
  6. Allow is a form POST carrying the site's CSRF token. Opening a URL never issues anything.
  7. The code. opensolr.com creates 32 random bytes, keeps only their SHA-256 bound to the account, the client, the redirect address and the challenge, valid for 60 seconds, and redirects to /app/callback?code=…&state=…. No page of this flow sends a Referer.
  8. Back to the app. Android opens the app for that address because opensolr.com publishes the app's certificate in assetlinks.json. If the browser shows the page instead, its button hands the same code to the app through opensolr-photos://auth.
  9. The app checks the state against the one it stored, in constant time, and forgets the stored pair whatever the result. A sign-in older than 15 minutes is refused.
  10. The exchange. The app posts the code and the verifier to /app/token. The server allows 20 attempts a minute per address, marks the code used with a single atomic update so it can never be redeemed twice, checks the verifier against the challenge, checks the account is still active, and answers the email, the account API key and the plan limits. Every refusal looks the same.
03 · Who is signed in, and what the app keeps

The identity is the person actually signed in to opensolr.com in the browser. If that person is visiting another account through Opensolr Teams, the app still receives their own account, never the visited one.

ValueWhereProtection
Account emailApp preferencesPrivate app storage
Account API keyApp preferencesAES-256-GCM with a key held in the Android Keystore
Index passwordApp preferencesThe same Keystore encryption
Pending verifier and stateApp preferences, 15 minutes at mostVerifier encrypted; both erased when used
When the key stops working

If Opensolr refuses the saved key, for example after the account's API key was changed, the running sync stops, a notification asks you to sign in again, and the app returns to its sign-in screen. Signing in again is the whole fix; the index is untouched. Signing out cancels every sync and forgets the account on the phone, while the index stays in your account.

Opensolr Photos is open source and MIT licensed. Questions about your Opensolr account, index or plan go to opensolr.com/contact; questions about the app itself belong on GitHub.

Opensolr Photos Documentation