├── README.md └── docs ├── end-user-help.md ├── public-api-terms.md ├── api-auth.md └── api.md /README.md: -------------------------------------------------------------------------------- 1 | nxapi znca API server 2 | --- 3 | 4 | This repository contains a server for generating `f` parameters required to authenticate to the Nintendo Switch Online app API. This was previously part of [nxapi](https://gitlab.fancy.org.uk/samuel/nxapi) ([GitHub](https://github.com/samuelthomas2774/nxapi)), a library and command line and Electron app for using Nintendo's smart device app APIs. 5 | 6 | This uses Frida to call the token generation functions in the Nintendo Switch Online app on a rooted Android device. 7 | 8 | ### Public API 9 | 10 | A server running this API is available at https://nxapi-znca-api.fancy.org.uk/api/znca. If you would like to use this please send me a message in the [nxapi Discord server](https://discord.com/invite/4D82rFkXRv). If your project authenticates as the user's Nintendo Account you must explain that their id_token will be sent to a third-party API, and include a link to here. 11 | 12 | Status is available at https://nxapi-status.fancy.org.uk. Usage stats are available at https://grafana.tt.fancy.org.uk/public-dashboards/442f37612eed4c4a829fd7025b07d152. 13 | 14 | Please read the requirements for using the public API in [docs/public-api-terms.md](docs/public-api-terms.md). 15 | 16 | See [docs/api.md](docs/api.md) for API usage details. 17 | -------------------------------------------------------------------------------- /docs/end-user-help.md: -------------------------------------------------------------------------------- 1 | nxapi f-generation API 2 | --- 3 | 4 | nxapi-znca-api is an API used by nxapi and other applications that use the Nintendo Switch Online app's API, including game-specific services such as SplatNet 3 and NookLink, to authenticate to Nintendo's servers. 5 | 6 | The f-generation API generates a value (known as `f`) normally generated by the Nintendo Switch Online app when you sign in with your Nintendo Account. To do this, it needs the Nintendo Account ID token the app uses to authenticate to it's own API (the API that nxapi and other applications use). 7 | 8 | No other information is required by the Nintendo Switch Online app's API for authentication, so it is possible to access the API as your account with only this token. The ID token does not allow full access to your Nintendo Account however, and does not contain your sign-in ID, email address, or password. The token includes the following information: 9 | 10 | - Your Nintendo Account ID 11 | - Your Nintendo Account country 12 | - Information about the token itself, such as when it expires 13 | 14 | When accessing a game-specific service, the API is used to generate another `f` value, using the token the Nintendo Switch Online app uses to access it's API after authenticating using an ID token. This token includes the following information: 15 | 16 | - Your Nintendo Switch Online app user ID 17 | - Your Nintendo Switch Online membership status (either active or inactive) 18 | - Your child restriction status (either 13+ or under 13) 19 | - Information about the token itself, such as when it expires 20 | 21 | This token does not include your Nintendo Account ID so cannot be linked to the first token. 22 | 23 | The f-generation API does not store Nintendo Account ID tokens or Nintendo Switch Online app tokens. The API does store the user identifier, either the Nintendo Account ID or the Nintendo Switch Online app user ID depending on the type of request, to prevent excessive and unnecessary requests from a single user, either due to malicious or misbehaving clients, as this would prevent other users from using the service. The API also stores request logs which include your network address and the User-Agent sent by the software used, which may contain limited information about your system. 24 | 25 | The f-generation API is developed and run by [@samuelthomas2774](https://github.com/samuelthomas2774). I do not maintain any software that uses this API other than nxapi; please contact the maintainers of the software you are using if you have any issues. 26 | -------------------------------------------------------------------------------- /docs/public-api-terms.md: -------------------------------------------------------------------------------- 1 | ### Requirements for developing clients using the public API 2 | 3 | - The `X-znca-Platform` and `X-znca-Version` headers *should* be sent, and may use the config endpoint to retrieve the latest version 4 | - The `X-znca-Client-Version` header *must* be sent and *must not* be set dynamically 5 | - The `timestamp` and `request_id` fields *should not* be sent (from 2.12.0, these will not work) 6 | - The `User-Agent` header *must* be sent and *must* contain your project's name and version, and contact details 7 | - The preferred format is `project/version (+url)`, e.g. `nxapi/1.0.0 (+https://github.com/samuelthomas2774/nxapi)`; libraries that use the API should include a User-Agent component for both the library and the dependent software, e.g. `library/1.0.0 (...) nxapi/1.0.0 (...)` 8 | - The client *must* authenticate to the API using credentials obtained via [nxapi-auth](https://nxapi-auth.fancy.org.uk) 9 | - Authentication using user credentials/authorisation is not required 10 | - You should use a separate client identifier for development 11 | - For confidential clients, i.e. clients that access the API via the developer's server, authentication must use a client secret or client assertion 12 | - For public clients, i.e. clients that access the API via the user's device, authentication may optionally use a client assertion or only the client identifier 13 | - The token should not be stored and can only be used by a single Coral user 14 | - The token should be refreshed using the returned refresh token when it expires if the client is still using the API 15 | - The client *should* attempt to imitate Nintendo's official apps as closely as possible 16 | - Where the below requirements include informing the user that data is sent to any non-Nintendo service, including this API and the service itself, the client/service *must* do so *before* asking the user to sign in using their Nintendo Account, and *must* require the user to explicitly acknowledge this before contacting non-Nintendo services 17 | - The client *must* cache tokens for their full validity period, unless deletion is requested, or access is no longer required, and *must* only renew tokens as Nintendo's official apps/web services do 18 | - You may want to include a link to [docs/end-user-help.md](./end-user-help.md) 19 | 20 | For clients that authenticate using a user's account: 21 | 22 | - The client *must* inform the user that their Nintendo Account id_token, coral token, and all data sent to and received from the Coral API will be sent to a third-party API 23 | - The client *must* include a link to this project 24 | 25 | For services that authenticate using a user's account via another server: 26 | 27 | - The service *must* inform the user that their Nintendo Account session token will be sent to/stored by your service 28 | - The service *may* use the authorisation code grant, without requesting the `offline` scope, instead of Nintendo's custom session token code grant as normally used by the Nintendo Switch Online app, when only temporary access to the user's account is required 29 | - The service *must* suitably encrypt stored Nintendo Account session tokens, and *must not* allow retrieval of session tokens 30 | - The service *must not* allow anyone other than the user who provided the session token/session token code/similar long-term token to cause the service to perform requests to Nintendo services using that user's account, including by administrators (this does not mean that you can't share data retrieved by that user with other users or services) 31 | - The service *must* provide an option to allow users to delete their Nintendo Account session tokens/similar provided tokens, and any cached tokens, and cease sending any requests to Nintendo services using their account immediately on request 32 | - The service *must* only perform requests to Nintendo services using a user's account in response to the user interacting with the service 33 | - The service *may* make automated requests to Nintendo services using a user's account, at a limited frequency, only if the user has explicitly allowed this, and has recently interacted with the service 34 | - The service *must* limit requests to this API to 1 concurrent request for users that are not interacting with the service (that means, when handling interactions for multiple users, multiple simultaneous requests can be sent, but only one automated request) 35 | - The service *must* appropriately handle errors, such as by deleting a user's session token if an `invalid_grant` error is received 36 | - The service *must not* automatically retry requests to this API, except for network errors where the connection is closed before a HTTP response is received, or as specified by the `Retry-After` header 37 | - The service *must not* automatically retry requests to Nintendo services, except for network errors where the connection is closed before a HTTP response is received 38 | -------------------------------------------------------------------------------- /docs/api-auth.md: -------------------------------------------------------------------------------- 1 | API authentication 2 | --- 3 | 4 | The API requires client authentication via [nxapi-auth](https://nxapi-auth.fancy.org.uk). 5 | 6 | This uses the standard OAuth 2 client credentials grant. In OAuth 2 terms: 7 | 8 | - nxapi-auth is the authorisation server 9 | - nxapi-znca-api is the resource server and itself the protected resource 10 | 11 | OAuth clients must be registered at https://nxapi-auth.fancy.org.uk/oauth/clients. Make sure you complete the client information section - this may be visible to users authenticating with the f-generation API in the future. 12 | 13 | ### Tokens 14 | 15 | Clients can obtain a token by sending an OAuth 2 token request to nxapi-auth. 16 | 17 | ```ts 18 | const params = new URLSearchParams(); 19 | 20 | params.append('grant_type', 'client_credentials'); 21 | params.append('client_id', import.meta.env.NXAPI_AUTH_CLIENT_ID); 22 | // optionally also a client assertion, or for confidential clients either a client assertion or client secret 23 | // if using a client assertion, client_id is optional 24 | // if the client already has a token, use the refresh_token grant instead 25 | params.append('scope', 'ca:gf ca:er ca:dr'); 26 | 27 | const response = await fetch('https://nxapi-auth.fancy.org.uk/api/oauth/token', { 28 | method: 'POST', 29 | headers: { 30 | 'Accept': 'application/json', 31 | }, 32 | body: params, 33 | }); 34 | 35 | const token = await response.json() as { 36 | access_token: string; 37 | token_type: 'Bearer'; 38 | expires_in: number; 39 | scope?: string; 40 | refresh_token?: string; 41 | }; 42 | ``` 43 | 44 | The returned token, including refresh token, is short-lived and must not be saved persistently. Instead, the client should always attempt to obtain a new token using it's client credentials if it does not already have a token. Tokens can only be used for a single Coral user; if the client authenticates using multiple Nintendo Accounts it must obtain a separate token for each user. 45 | 46 | If the client is attempting to refresh a token using the `refresh_token` grant and receives an `invalid_grant` error it should attempt to obtain a new token using it's client credentials. If the client receives an `invalid_grant` error in any other case it should not retry. 47 | 48 | - [RFC 6749: The OAuth 2.0 Authorization Framework](https://datatracker.ietf.org/doc/html/rfc6749) 49 | - [Client Credentials Grant](https://datatracker.ietf.org/doc/html/rfc6749#section-4.4) 50 | - [Issuing an Access Token](https://datatracker.ietf.org/doc/html/rfc6749#section-5) 51 | - [Refreshing an Access Token](https://datatracker.ietf.org/doc/html/rfc6749#section-6) 52 | - [RFC 7521: Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants](https://datatracker.ietf.org/doc/html/rfc7521) 53 | - [Using Assertions for Client Authentication](https://datatracker.ietf.org/doc/html/rfc7521#section-4.2) 54 | 55 | #### Client assertions 56 | 57 | The token endpoint supports `urn:ietf:params:oauth:client-assertion-type:jwt-bearer` assertions. This must be configured in nxapi-auth. 58 | 59 | JWTs must have these claims: 60 | 61 | - `aud`, exactly or an array including `https://nxapi-auth.fancy.org.uk` 62 | - `typ`, exactly `client_assertion` 63 | - `exp`, and not be expired 64 | 65 | JWTs must also: 66 | 67 | - Have a `jku` value in the token header, matching a JSON Web Key Set URI configured in nxapi-auth 68 | - Have a `kid` value in the token header 69 | - Have a `alg` value in the token header of `RS256` 70 | 71 | ### Token authentication 72 | 73 | Requests to the f-generation API should send the token in the `Authorization` header. 74 | 75 | If the client receives an `invalid_token` error it should attempt to refresh the token. 76 | 77 | - [RFC 6750: The OAuth 2.0 Authorization Framework: Bearer Token Usage](https://datatracker.ietf.org/doc/html/rfc6750) 78 | 79 | ### Authorisation scope 80 | 81 | Tokens have limited access to the f-generation API by the requested scope. 82 | 83 | Available token scopes are listed below. All access scopes have two names, one used by nxapi-auth and one used by the f-generation API. When requesting a token, use the nxapi-auth name. 84 | 85 | nxapi-auth | nxapi-znca-api | Description 86 | ------------|-----------------------|--------------- 87 | `ca:gf` | `generate-f` | Allows the client to use the `/f` endpoint. 88 | `ca:er` | `encrypt-request` | Allows the client to use the `/encrypt-request` endpoint, and the `encrypt_token_request` field in the `/f` endpoint. 89 | `ca:dr` | `decrypt-response` | Allows the client to use the `/decrypt-response` endpoint. 90 | `ca:da` | `decrypt-any` | Allows the client to use the `/decrypt-response` endpoint to decrypt data that is not a valid Coral response. 91 | 92 | All clients can request the `ca:gf`, `ca:er` and `ca:dr` scopes. `ca:da` requires approval and is limited to confidential clients; this scope is intended for development only. 93 | -------------------------------------------------------------------------------- /docs/api.md: -------------------------------------------------------------------------------- 1 | API usage 2 | --- 3 | 4 | The server has four endpoints, `/api/znca/f` and `/api/znca/config`, which are compatible with [the imink API](https://github.com/JoneWang/imink/wiki/imink-API-Documentation)'s `/f` and `/config` endpoints, and `/api/znca/encrypt-request` and `/api/znca/decrypt-request`, which are used for request encryption in 3.0.1 and later. 5 | 6 | > From June 2025, authentication is required. See [api-auth.md](api-auth.md) for more information. 7 | 8 | ### `/config` 9 | 10 | `/api/znca/config` can be used to check which app versions are available. 11 | 12 | `nso_version` is the latest version supported by the server. 13 | 14 | The `versions` field is not supported by the imink API. `worker_count` is provided for monitoring/debugging and should not be used by clients. 15 | 16 | ```jsonc 17 | { 18 | "versions": [ 19 | { 20 | "platform": "Android", 21 | "name": "com.nintendo.znca", 22 | "version": "2.4.0", 23 | "build": 3467, 24 | "worker_count": 2 25 | }, 26 | { 27 | "platform": "Android", 28 | "name": "com.nintendo.znca", 29 | "version": "2.5.0", 30 | "build": 3828, 31 | "worker_count": 2 32 | } 33 | ], 34 | "nso_version": "2.5.0" 35 | } 36 | ``` 37 | 38 | ### `/f` 39 | 40 | The following data should be sent as JSON to generate an `f` parameter: 41 | 42 | ```ts 43 | interface ZncaApiFRequest { 44 | /** 45 | * `"1"` or `1` for Coral (Nintendo Switch Online app) authentication (`Account/Login` and `Account/GetToken`). 46 | * `"2"` or `2` for web service authentication (`Game/GetWebServiceToken`). 47 | */ 48 | hash_method: '1' | '2' | 1 | 2; 49 | 50 | /** 51 | * The token used to authenticate to the Coral API: 52 | * The Nintendo Account `id_token` for Coral authentication. 53 | * The Coral access token for web service authentication. 54 | */ 55 | token: string; 56 | /** 57 | * The current timestamp in milliseconds, either as a number or a string. 58 | */ 59 | timestamp?: string | number; 60 | /** 61 | * A random (v4) UUID. 62 | */ 63 | request_id?: string; 64 | 65 | /** 66 | * The user's Nintendo Account ID from https://api.accounts.nintendo.com/2.0.0/users/me (`id`). 67 | * 68 | * For Coral authentication (hash method 1) this will be set automatically from the `token` if not provided. 69 | * (Although providing it is recommended.) 70 | * For web service authentication (hash method 2) this must be provided. If it is not provided an empty string 71 | * will be used, which will cause the resulting f token to be rejected if/when Nintendo starts validating this. 72 | */ 73 | na_id?: string; 74 | /** 75 | * The user's Coral user ID from Account/Login or Account/GetToken (`result.user.id`). 76 | * 77 | * Only used for web service authentication (hash method 2). 78 | * 79 | * This will be set automatically from the `token` if not provided. (Providing it is recommended.) 80 | */ 81 | coral_user_id?: string; 82 | 83 | /** 84 | * Additional data used in the Account/Login, Account/GetToken or Game/GetWebServiceToken request. 85 | * 86 | * If provided the API will return a base64-encoded `encrypted_token_request` field containing the encrypted 87 | * request body to send to the Coral API. 88 | * 89 | * The `f`, `requestId` and `timestamp` fields in `parameter` are required and must be set to an empty string 90 | * or `0`. This will be replaced with the generated values. 91 | */ 92 | encrypt_token_request?: { 93 | url: string; 94 | parameter: 95 | import('nxapi/coral').AccountLoginParameter | 96 | import('nxapi/coral').AccountTokenParameter | 97 | import('nxapi/coral').WebServiceTokenParameter; 98 | }; 99 | } 100 | ``` 101 | 102 | As the server can support multiple versions of the Nintendo Switch Online app (which generate different `f` values), the `X-znca-Platform` and `X-znca-Version` headers should be used to indicate which version the client is using. 103 | 104 | The `X-znca-Client-Version` header is used to check if the client may be incompatible with newer coral versions and should never be set dynamically. From 3.1.0, this is a random per-client value issued by nxapi-auth. 105 | 106 | > Due to changes to Nintendo's API on [23/08/2022](https://github.com/samuelthomas2774/nxapi/discussions/10#discussioncomment-3464443) the `timestamp` parameter should not be sent. If the `timestamp` or `request_id` parameters are not sent their values will be generated and returned in the response. Note that unlike the imink API and [nsotokengen](https://github.com/clovervidia/nsotokengen), only parameters not included in the request will be included in the response. 107 | > 108 | > From 2.12.0, the `timestamp` and `request_id` parameters cannot be used. 109 | 110 | ```sh 111 | # Make imink-compatible API requests using curl 112 | curl --header "Content-Type: application/json" --header "X-znca-Platform: Android" --header "X-znca-Version: 2.4.0" \ 113 | --data '{"hash_method": "1", "token": "...", "na_id": "0000000000000000"}' "http://[::1]:12345/api/znca/f" 114 | 115 | # Use the znca API server in nxapi 116 | # This should be set when running any nso or web service commands as the access token will be refreshed automatically when it expires 117 | ZNCA_API_URL=http://[::1]:12345/api/znca nxapi nso ... 118 | ``` 119 | 120 | Information about the device and the Nintendo Switch Online app, as well as information on how long the request took to process will be included in the response headers. 121 | 122 | Header | Description 123 | --------------------------------|------------------ 124 | `X-Device-Id` | ADB device ID (IP address and ADB port) of the Android device 125 | `X-Android-Build-Type` | Android build type, e.g. `user` 126 | `X-Android-Release` | Android release/marketing version, e.g. `8.0.0` 127 | `X-Android-Platform-Version` | Android SDK version, e.g. `26` 128 | `X-znca-Platform` | Device platform - always `Android` 129 | `X-znca-Version` | App release/marketing version, e.g. `2.2.0` 130 | `X-znca-Build` | App build/internal version, e.g. `2832` 131 | 132 | The following performance metrics are included in the `Server-Timing` header: 133 | 134 | Name | Description 135 | ------------|------------------ 136 | `validate` | Time validating the request body. 137 | `attach` | Time waiting for the device to become available, start frida-server, start the app and attach the Frida script to the app process. This metric will not be included if the server is already connected to the device. 138 | `queue` | Time waiting for the processing thread to become available. 139 | `init` | Time waiting for `com.nintendo.coral.core.services.voip.Libvoipjni.init`. 140 | `process` | Time waiting for `com.nintendo.coral.core.services.voip.Libvoipjni.genAudioH`/`genAudioH2`. 141 | 142 | ### `/encrypt-request` 143 | 144 | The following data should be sent as JSON to encrypt a request body to send to the Coral API. 145 | 146 | ```ts 147 | interface ZncaApiEncryptRequestRequest { 148 | /** 149 | * The URL of the Coral API request, e.g. "https://api-lp1.znc.srv.nintendo.net/v4/Friend/List". 150 | */ 151 | url: string; 152 | /** 153 | * The Coral token. 154 | * 155 | * This is the token sent in the `Authorization` header in the request to the Coral API. For requests that do 156 | * not send a token, e.g. Account/Login and Account/GetToken, this should be null, but is required for all 157 | * requests that do send a token. 158 | */ 159 | token: string | null; 160 | /** 161 | * The request body of the Coral API request. 162 | * 163 | * This must be provided as a plain JSON-encoded string, e.g. "{\"parameter\":{}}". 164 | */ 165 | data: string; 166 | } 167 | ``` 168 | 169 | The encrypted data will be returned as binary data with the content type `application/octet-stream`. This also supports returning JSON-encoded data with a base64-encoded `data` field. You should always send an `Accept` header to set the response type. 170 | 171 | This endpoint currently does not return information about the device used to process the request. 172 | 173 | ### `/decrypt-response` 174 | 175 | The following data should be sent as JSON to decrypt a response from the Coral API. 176 | 177 | ```ts 178 | interface ZncaApiDecryptResponseRequest { 179 | /** 180 | * The response received from the Coral API. 181 | * 182 | * This must be base64-encoded. 183 | */ 184 | data: string; 185 | } 186 | ``` 187 | 188 | The decrypted data will be returned as plain text, which should be valid JSON, with the content type `text/plain`. This also supports returning JSON-encoded data with a string `data` field. You should always send an `Accept` header to set the response type. 189 | 190 | While the app can decrypt data it encrypts itself, this endpoint will only return decrypted data that contains a valid Coral API response. 191 | 192 | This endpoint currently does not return information about the device used to process the request. 193 | 194 | ### Health monitoring 195 | 196 | An additional endpoint is available for monitoring service availability. 197 | 198 | When sending a GET request to `/api/znca/health`, the server will attempt to generate an `f` token if one was not successfully generated in the last 30 seconds, and return the timestamp the last `f` token was generated. The same headers as above will be returned, excluding validation time. 199 | 200 | `/api/znca/devices` will return the list of worker devices connected to the server. 201 | 202 | These endpoints are only provided for monitoring/debugging purposes. 203 | 204 | ### Errors 205 | 206 | Error responses are always sent as JSON, and will include an `error` field, with an appropriate HTTP status code. Some errors may also include a human-readable `error_description` field intended for client developers. 207 | 208 | `error` | Description 209 | ------------------------------------|--------------- 210 | `unknown_error` (500) | Misc. error, may include an `error_description` with more information 211 | `service_unavailable` (503) | The server was unable to connect to a worker device, or it took too long for a worker to become available 212 | `unauthorised` (401) | No authentication was provided but is required, see [api-auth.md](api-auth.md) 213 | `invalid_token` (401) | The access token was invalid/expired 214 | `insufficient_scope` (403) | The access token scope does not allow use of the requested endpoint or optional request field 215 | `invalid_request` (400) | Request parameters are not valid, may include an `errors` and/or `warnings` field with more information 216 | `invalid_request` (415) | Invalid request body/unsupported content type 217 | `request_parameter_not_set` (400) | Request parameters are not valid 218 | `unsupported_platform` (400) | Unsupported `X-znca-Platform` 219 | `unsupported_version` (406) | Unsupported `X-znca-Version` 220 | `incompatible_client` (400) | The `X-znca-Client-Version` header indicates the client may not be compatible with the Coral version it requested - this means the client likely needs updating 221 | `rate_limit` (429) | See [rate limits](#rate-limits) 222 | 223 | Error responses will also include a `debug_id` field containing a random string that may be used to find more information about errors. This is also included in the `X-Trace-Id` header in all responses. 224 | 225 | Some success responses will also include a `warnings` field, usually if request data can be accepted by the f-generation API but may return tokens that could be rejected by Nintendo. 226 | 227 | ### Rate limits 228 | 229 | Request type | Rate limit | Key 230 | --------------------------------------------|---------------------------|--------------- 231 | Coral authentication (hash method 1) | 10 requests/60 minutes | Nintendo Account user 232 | Web service authentication (hash method 2) | 20 requests/30 minutes | Coral user 233 | Request encryption | TODO | nxapi-auth session 234 | Response decryption | TODO | nxapi-auth session 235 | 236 | f-generation requests with a `encrypt_token_request` field currently are only counted as coral/web service auth requests; the request encryption rate limit is not used. 237 | --------------------------------------------------------------------------------