Skip to content

Meta login and ownership

Marco Ceccon edited this page Oct 12, 2026 · 2 revisions

This page covers the Meta side of setup. It lists the login that gives the phone its tokens, the two receipts that make the phone the owner, and the calls the phone makes to Meta. The trust check that runs on later connections is on Identity-and-trust.

Setup contacts Meta in two places. First, the user logs in to a Meta account, and the phone exchanges that login for a token. Second, Meta's hardware service issues two receipts that name the phone as owner. After setup, the connection path makes no Meta call. The glasses check the phone's key over the link itself.

The sequence below shows one setup, from the Meta login to the glasses accepting the phone as owner.

sequenceDiagram
    participant Phone
    participant Meta
    participant Glasses
    Phone->>Meta: Authorize page (accounts.meta.com/oidc/)
    Meta-->>Phone: Redirect with code and state
    Phone->>Meta: Token exchange with the code
    Meta-->>Phone: access_token, the FRLA
    Phone->>Meta: AR login with the AR app token and the FRLA
    Meta-->>Phone: ARAe
    Phone->>Glasses: Secure link up
    Phone->>Glasses: Identity request (svc36)
    Glasses-->>Phone: Identity response with device certificate and serial
    Phone->>Glasses: Skip challenge
    Glasses-->>Phone: Skip challenge ack with nonce
    Phone->>Meta: pair_request with certificate, serial, nonce and owner public key
    Meta-->>Phone: Pending receipt and signature
    Phone->>Glasses: Start change owner request with the pending receipt
    Glasses-->>Phone: Start change owner response with the device pending receipt
    Phone->>Meta: pair with the device pending receipt
    Meta-->>Phone: Final receipt and signature
    Phone->>Glasses: Finish change owner request with the final receipt
    Glasses-->>Phone: Finish change owner ack
Loading

Meta login

The login runs on Meta's own page and ends at the redirect URI. The phone then exchanges the code for a token.

  1. The phone builds the authorize URL for accounts.meta.com/oidc/. It sends a fixed app id, scope openid, response type code, the redirect URI https://accounts.meta.com/native/oidc/redirect/metaai and a state of 16 random bytes, base64url without padding.
  2. The user signs in on Meta's page.
  3. The login ends at the redirect URI. The phone reads code and state from that URL. The redirect page is not loaded, and the phone does not read the page content.
  4. The phone rejects a redirect whose state differs from the one it sent. A redirect without a code fails.
  5. The phone posts the code to api.accounts.meta.com/native/oidc/token-exchange/ with the fields mt_app_id, oidc_auth_code and redirect_uri. The response must hold access_token and user_id. A 500 answer means the code belongs to another flow.
  6. The access_token from step 5 is the FRLA.

Token kinds

The phone uses four credentials. The table gives their names, sources and uses.

Name Source Used for
FRLA access_token of the token exchange Field frl_access_token on the AR login
ARAe access_token of the AR login Field user_access_token on the hardware calls, with user_token_universe set to ar
AR app token A fixed app token, shown here as <AR app token> Field access_token on the AR login
HW app token A fixed app token, shown here as <HW app token> Field access_token on the hardware calls

The AR login is ar.graph.meta.com/login. The phone sends the AR app token and the FRLA. It also sends two new random UUIDs as logging_session_id and device_id, format set to json, and the flags generate_session_cookies and generate_analytics_claim set to 1. The response access_token is the ARAe. A response with an error field is a failure, and its message gives the cause.

The phone runs the AR login before each call that needs a Meta token. A FRLA that Meta refuses fails the AR login.

Ownership receipt and change owner

Each pair of glasses holds one owner key, an EC P-256 key. Change owner replaces that key with the phone's key. Meta's hardware service issues two receipts for the change. Each receipt is Meta's signature over a JSON body. The glasses take the receipts over the identity service, svc36. The phone calls the hardware host graph.facebook-hardware.com.

On the link, a receipt is a message with field 1 for the signature and field 2 for the JSON body.

The change-owner flow runs in this order. The phone opens one channel on svc36 and sends its messages on it. Only the first message on a channel carries the service id and the message type. Later messages report service id 0.

Step Type (decimal, hex) Direction Body
Identity request 12288 (0x3000) Phone to glasses Empty
Identity response 12289 (0x3001) Glasses to phone Field 1 device certificate (DER), field 2 serial as ASCII text
Skip challenge 8192 (0x2000) Phone to glasses Empty
Skip challenge ack 8193 (0x2001) Glasses to phone Field 1 nonce, 16 bytes
Start change owner request 8194 (0x2002) Phone to glasses Pending receipt from Meta
Start change owner response 8195 (0x2003) Glasses to phone Device pending receipt: field 1 signature, field 2 JSON with the certificate
Finish change owner request 8196 (0x2004) Phone to glasses Final receipt from Meta
Finish change owner response 8197 (0x2005) Glasses to phone Empty acknowledgement

The hardware calls run between those messages:

  1. pair_request is a form POST to graph.facebook-hardware.com/pair_request, gzip compressed. Its fields are access_token (HW app token), user_access_token (ARAe), user_token_universe (ar), pair_protocol_version (4), device_cert (base64 of the device certificate), serial_number and additional_data. The last is JSON text with device_nonce (base64 of the nonce from the skip challenge), app_pubkey (base64 of the phone's 64-byte public key) and secondary_cert (empty).
  2. The response holds pending_ownership_receipt and receipt_signature (base64). When the receipt body is an object, the phone writes it back as JSON the way Python's json.dumps does, so the bytes match the reference client.
  3. The phone sends the pending receipt to the glasses in step 8194.
  4. The glasses answer with a device pending receipt in step 8195.
  5. pair is a form POST to the same host. It sends device_pending_ownership_receipt (the JSON text), device_pending_ownership_receipt_signature (base64) and the common fields. The field ephemeral_pairing_flag is left out for a normal pairing.
  6. The response holds final_ownership_receipt and its signature. The phone sends the final receipt to the glasses in step 8196.
  7. The glasses acknowledge in step 8197. The phone reads serial and user_id from the final receipt body.

An HTTP status of 400 or more fails the step. A body with an error field fails with its message. An error on the channel comes as a status frame, and it fails the step that waits for a reply.

What Meta sees and when

Meta sees the account login, the glasses' certificate and serial number, and the phone's owner public key. The phone sends no user name and no phone serial.

When Host and call What the phone sends
Login, once per sign-in accounts.meta.com/oidc/, then api.accounts.meta.com/native/oidc/token-exchange/ The typed login on Meta's page, the fixed app id, the state, the code, the redirect URI and a fixed user agent that names the Meta AI Android app
Each call that needs a Meta token ar.graph.meta.com/login The AR app token, the FRLA, two new random UUIDs and the session and analytics flags
Setup, at the pair request graph.facebook-hardware.com/pair_request The device certificate, the serial number, the device nonce, the owner public key and the ARAe
Setup, at the pair graph.facebook-hardware.com/pair The device pending receipt and its signature
After setup None Nothing. The connection path makes no Meta call

What Meta keeps, and for how long, is not known.

Reference code: WebLogin.kt, Frla.kt, Provision.kt, ProvisionSession.kt

Open questions

  • Unknown: whether the glasses verify the receipt signatures. The glasses' check of the final receipt is not visible on the link. The phone reads only the acknowledgement and the status frames.
  • The lifetime of a FRLA is not known. A refusal from Meta is the only sign that a login has expired.
  • Unknown: whether any call needs the universe value fb. Setup uses only ar.

Clone this wiki locally