{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Backend setup","meta":[{"name":"robots","content":"noindex"}],"llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"backend-setup","__idx":0},"children":["Backend setup"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Your backend must support OAuth 2.0 token exchange to obtain Spotnana tokens on behalf of your users."," ","This page explains the backend setup process:"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"get-client-credentials-from-spotnana","__idx":1},"children":["Get client credentials from Spotnana"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Spotnana will provide you with a unique ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_id"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_secret"]}," which you'll use to request an access token every time a user logs in to the platform."," ","Store the client secret securely and never expose it in your codebase."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"provide-a-json-web-key-jwks-endpoint","__idx":2},"children":["Provide a JSON Web Key (JWKS) endpoint"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["During the setup, you must provide a ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://datatracker.ietf.org/doc/html/rfc7517"},"children":["JWKS"]}," endpoint and a sample ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://en.wikipedia.org/wiki/JSON_Web_Token"},"children":["JSON Web token"]}," (JWT) payload which Spotnana will use"," ","to verify the identity of the logged-in user during token exchange."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"a-jwks-endpoint-url","__idx":3},"children":["A JWKS endpoint URL"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You must host a publicly accessible HTTPS endpoint that exposes your ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://en.wikipedia.org/wiki/RSA_cryptosystem"},"children":["RSA public keys"]}," in a"," ","standard JSON Web Key (JWKS) format (i.e., the ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://datatracker.ietf.org/doc/html/rfc7517"},"children":["RFC 7517"]}," format)."," ","When a user logs in and your backend system submits a JSON Web Token (JWT) during token exchange,"," ","Spotnana fetches the public key from this endpoint to validate the token's signature."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Your JWKS endpoint must meet the following requirements:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["It must not require authentication."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["It must include a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["kid"]}," (Key ID) for each key. This ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["kid"]}," must match the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["kid"]}," in the JWT header so Spotnana can authenticate the request."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"sample-jwt-payload","__idx":4},"children":["Sample JWT payload"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You must also provide Spotnana with a decoded sample of the JSON Web Token (JWT) which your system will generate."," ","We the user's email address in the payload to map the user in the Spotnana platform."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A JWT has three Base64URL-encoded parts separated by dots: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["<header>.<payload>.<signature>"]},"."," ","The signature is computed using the encoded header and the payload."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Here's an example of an encoded JWT:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"\neyJraWQiOiJteS1rZXktaWQtMSIsImFsZyI6IlJTMjU2In0.eyJlbWFpbCI6ImpvaG4uZG9lQGN1c3RvbWVyLmNvbSIsImlzcyI6Imh0dHBzOi8vYXV0aC5jdXN0b21lci5jb20iLCJzdWIiOiIxM2Y3OTgyZC0xZjc4LTQ2ZTItYTg0My0zMjczNTY4ZmNlODkiLCJhdWQiOiJzcG90bmFuYSIsImlhdCI6MTcwOTA3ODQwMCwiZXhwIjoxNzA5MDgyMDAwfQ.<RS256 signature>\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The decoded header must use the RS256 algorithm and include a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["kid"]}," that matches a key in your JWKS endpoint:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"alg\": \"RS256\",\n  \"kid\": \"my-key-id-1\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The decoded payload must include the user's email at the root level as shown below:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"email\": \"john.doe@customer.com\",\n  \"pid\": \"13f7982d-1f78-46e2-a843-3273568fce89\",\n  \"iss\": \"https://auth.customer.com\",\n  \"sub\": \"13f7982d-1f78-46e2-a843-3273568fce89\",\n  \"aud\": \"spotnana\",\n  \"iat\": 1709078400,\n  \"exp\": 1709082000\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"blockquote","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Notes:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The email must be present in the decoded payload with the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["email"]}," field as shown in the above sample. If the name of the parameter is different (e.g., ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["userEmail"]},") or if it's nested within a different field (e.g., ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["user.email"]},") then contact your Spotnana representative to configure this custom mapping."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The email address must be the same as the one used to create the user's profile on the Spotnana platform."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Only the ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://en.wikipedia.org/wiki/JSON_Web_Token"},"children":["RS256"]}," (RSA with SHA-256) algorithm is supported for JWT signature generation and validation."]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"token-exchange-request","__idx":5},"children":["Token exchange request"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To obtain a Spotnana access token on behalf of the user, your system must send a POST request to the ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/openapi/authapi/authentication/fetchoauth2token"},"children":["OAuth token generation"]}," endpoint."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Here's a sample API request schema:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"shell","header":{"controls":{"copy":{}}},"source":"curl -X POST \"https://api-ext-sboxmeta.partners.spotnana.com/v2/auth/oauth2-token\" \\\n  -d \"grant_type=urn:ietf:params:oauth:grant-type:token-exchange\" \\\n  -d \"client_id=<SPOTNANA_CLIENT_ID>\" \\\n  -d \"client_secret=<SPOTNANA_CLIENT_SECRET>\" \\\n  -d \"subject_token=<SIGNED_JWT_WITH_USER_EMAIL>\" \\\n  -d \"subject_token_type=urn:ietf:params:oauth:token-type:jwt\" \\\n  -d \"scope=openid\"\n","lang":"shell"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Here's a sample response:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"access_token\": \"eyJraWQiOi...\",\n  \"refresh_token\": \"eyJjdHkiOi...\",\n  \"token_type\": \"Bearer\",\n  \"expires_in\": 3600,\n  \"scope\": \"openid\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The table below explains the different parameters used in the ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/docs/openapi/authapi/authentication/fetchoauth2token"},"children":["OAuth token generation"]}," API request:"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"width":"25%","data-label":"Parameter"},"children":["Parameter "]},{"$$mdtype":"Tag","name":"th","attributes":{"width":"15%","data-label":"Required?"},"children":["Required? "]},{"$$mdtype":"Tag","name":"th","attributes":{"width":"60%","data-label":"Description"},"children":["Description "]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["grant_type"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Must contain the value: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["urn:ietf:params:oauth:grant-type:token-exchange"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_id"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Your Spotnana client ID."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_secret"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Your Spotnana client secret."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["subject_token"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Your application's signed JWT containing the user's email. Spotnana validates the signature using your JWKS public key and extracts the email to identify the user."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["subject_token_type"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Must contain the value: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["urn:ietf:params:oauth:token-type:jwt"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["scope"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Must contain the value: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["openid"]},"."]}]}]}]}]}]},"headings":[{"value":"Backend setup","id":"backend-setup","depth":1},{"value":"Get client credentials from Spotnana","id":"get-client-credentials-from-spotnana","depth":2},{"value":"Provide a JSON Web Key (JWKS) endpoint","id":"provide-a-json-web-key-jwks-endpoint","depth":2},{"value":"A JWKS endpoint URL","id":"a-jwks-endpoint-url","depth":3},{"value":"Sample JWT payload","id":"sample-jwt-payload","depth":3},{"value":"Token exchange request","id":"token-exchange-request","depth":2}],"frontmatter":{"seo":{"title":"Backend setup"}},"lastModified":"2026-04-16T07:58:33.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/integration/iframe/iframe-backend-setup","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}