Home docs switch Device Authentication (DAuth)
Post

Device Authentication (DAuth)

URL: https://dauth-lp1.ndas.srv.nintendo.net

Many Switch servers can only be accessed after obtaining a token from the dauth server. The dauth server only accepts requests with a valid client certificate. Every Switch has its own client certificate, which stored in PRODINFO.

Because the certificate is signed by Nintendo there is only one way to get a valid certificate: buy a Switch and dump it.

The dauth server takes form-encoded requests and responds with json-encoding. It uses base64url, and the client does not add any padding characters.

Headers

HeaderDescription
Hostdauth-lp1.ndas.srv.nintendo.net
User-AgentUser agent
Accept*/*
X-Nintendo-PowerStateFA (fully awake) or HA (half awake) (7.0.0 and later, see note below)
Content-LengthContent length
Content-Typeapplication/x-www-form-urlencoded

The X-Nintendo-PowerState header is only present on system version 7.0.0 and later. In 7.0.0, there is a space between X-Nintendo-PowerState and the colon. This was fixed in 7.0.1.

User Agents

System VersionUser agent
1.0.0libcurl (nnAccount; 789f928b-138e-4b2f-afeb-1acae821d897; SDK 0.16.29.0; Add-on 0.11.29.0)
2.0.0 - 2.3.0libcurl (nnAccount; 789f928b-138e-4b2f-afeb-1acae821d897; SDK 1.3.0.0; Add-on 1.3.0.0)
3.0.0 - 3.0.2libcurl (nnAccount; 789f928b-138e-4b2f-afeb-1acae821d897; SDK 3.4.0.0; Add-on 3.4.0.0)
4.0.0 - 4.1.0libcurl (nnAccount; 789f928b-138e-4b2f-afeb-1acae821d897; SDK 4.4.0.0; Add-on 4.4.0.0)
5.0.0 - 5.1.0libcurl (nnDauth; 789f928b-138e-4b2f-afeb-1acae821d897; SDK 5.3.0.0; Add-on 5.3.0.0)
6.0.0 - 6.1.0libcurl (nnHttp; 789f928b-138e-4b2f-afeb-1acae821d897; SDK 6.4.0.0; Add-on 6.4.0.0)
6.2.0libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 6.4.0.0)
7.0.0 - 7.0.1libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 7.3.0.0)
8.0.0libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 8.2.99.0)
8.0.1 - 8.1.1libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 8.2.0.0)
9.0.0 - 9.2.0libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 9.3.0.0)
10.0.0 - 10.2.0libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 10.4.0.0)
11.0.0 - 11.0.1libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 11.4.0.0)
12.0.0 - 12.1.0libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 12.3.0.0)
13.0.0libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 13.3.0.0)
13.1.0 - 13.2.1libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 13.4.0.0)
14.0.0 - 14.1.2libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 14.3.0.0)
15.0.0 - 15.0.1libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 15.3.0.0)
16.0.0 - 16.1.0libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 16.2.0.0)
17.0.0 - 17.0.1libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 17.5.0.0)
18.0.0libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 18.3.0.0)

Methods

In API version 3 and later, one must perform a cryptographic challenge to obtain a device token or edge token:

The following methods return a device token as JWT:

The following methods return a different kind of device token:

System Versions

SystemAPI
1.0.0 - 3.0.0v1
3.0.1 - 4.1.0v2
5.0.0 - 6.1.0v3
6.2.0v4
7.0.0 - 8.1.1v5
9.0.0 - 12.1.0v6
13.0.0 - 18.0.0v7

API Changes

APIChangelog
v1Initial version.
v2The API path is obfuscated with random hex string.
v3The challenge was added and the format of the system version parameter was changed. Device authentication now requires knowledge of the master key, and the client can no longer fake an unreleased system version. Also, the edge_token route was added.
v4The prefix of the system version digest was changed.
v5The X-Nintendo-PowerState header was added. The API path is no longer obfuscated.
v6The ist parameter was added.
v7The vendor_id parameter was added to the edge token request.

Challenge Request

ParamDescription
key_generationMaster key revision

Response:

FieldDescription
challengeBase64-encoded challenge (32 bytes)
dataBase64-encoded AES key required for MAC calculation (16 bytes)

The data value never changes, but it depends on the given key generation. It is even consistent across environments. The challenge value is valid for one minute.

Device Token Request

This method returns a device token as JWT.

Version 1 - 2

ParamDescription
client_idApplication-specific client id
system_versionSystem version (%08x)

Response on success:

FieldDescription
expires_inExpiration in seconds (86400)
device_auth_tokenDevice token

Version 3 - 5

A challenge was added and the format of the system version parameter was changed:

ParamDescription
challengeBase64-encoded challenge
client_idApplication-specific client id
key_generationMaster key revision
system_versionSystem version digest
macBase64-encoded AES-CMAC of all previous fields in form-encoding

The key for the AES-CMAC is calculated as follows, using AES-ECB:

  1. The aes_kek_generation_source is decrypted with the master key.
  2. The dauth key source is decrypted with the key from step 1.
  3. The key from the data field of the challenge is decrypted with the key from step 2.

The dauth key source is: 8be45abcf987021523ca4f5e2300dbf0

Version 6 - 7

An ist parameter was added:

ParamDescription
challengeBase64-encoded challenge
client_idApplication-specific client id
isttrue or false (depends on platform region)
key_generationMaster key revision
system_versionSystem version digest
macBase64-encoded AES-CMAC of all previous fields in form-encoding

Edge Token Request

This method returns a different kind of device token. Up to v6, it takes the same parameters as /device_auth_token.

Response on success:

FieldDescription
expires_inExpiration in seconds (86400)
dtokenDevice token

Version 7

A vendor_id parameter was added:

ParamDescription
challengeBase64-encoded challenge
client_idApplication-specific client id
isttrue or false (depends on platform region)
key_generationMaster key revision
system_versionSystem version digest
vendor_idakamai, llnw or lumen
macBase64-encoded AES-CMAC of all previous fields in form-encoding

Master Key Revisions

System versionKey generation
5.0.0 - 5.1.05
6.0.0 - 6.1.06
6.2.07
7.0.0 - 8.0.18
8.1.0 - 8.1.19
9.0.0 - 9.0.110
9.1.0 - 12.1.011
13.0.0 - 13.2.113
14.0.0 - 14.1.214
15.0.0 - 15.0.115
16.0.0 - 16.1.016
17.0.0 - 18.0.017

Known Client IDs

Client IDDescriptionEdge
146c8ac7b8a0db52SCSI storageYes
3117b250cab38f45AtumYes
41f4a6491028e3c4Pushmo and TagayaYes
67bf9945b45248c6BCATYes
6ac5a6873fe5f68cSATA storageNo
75fe236362ff5f8b?No
81333c548b2e876dAccount serverNo
83b72b05dc3278d7NPNSNo
8f849b5d34778d8eAAuth and BaaSNo
93af0acb26258de9Beach and BugyoYes
bad8156f44ac935aSProfileNo
d5b6cac2c1514c56DragonsNo
dc656ea03b63cf68Parental controlsNo
df51c436bc01c437PrepoNo

Errors

On error, the server sends the following response:

FieldDescription
errorsList of errors

Every error is encoded like this:

FieldDescription
codeError code (string with 4 digits)
messageError message

Known Errors

For more detailed descriptions, see below.

Most errors use HTTP status code 400. The only known exception is error 0009, which uses status code 500.

CodeMessage
0004Unauthorized device.
0007System update is required.
0008Device has been banned.
0009Internal Server Error.
0010?
0011?
0013?
0014Invalid parameter in request.
0015Invalid parameter in request.
0016Invalid parameter in request.
0017This device might be broken.
0018?
0019?
0020?
0021?
0022?
0023?
0024?
0025?
0026?
0027?
0028?
0029?
0030?
0031?
CodeDescription
0004The device certificate belongs to a different environment.
0007A system update is required.
0008The device is banned permanently.
0009An internal server error has occurred.
0014Generic error.
0015The challenge has expired.
0016The MAC is wrong.
0017The device is banned.

Examples

Note that the client must always use a valid device certificate as the client certificate. If the client does not provide a certificate, the nginx server rejects the request:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
HTTP/1.1 400 Bad Request
Server: nginx
Date: Sun, 26 Sep 2021 19:21:43 GMT
Content-Type: text/html
Content-Length: 246
Connection: close

<html>
<head><title>400 No required SSL certificate was sent</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
<hr><center>nginx</center>
</body>
</html>

Before anything else, one must obtain a challenge:

1
2
3
4
5
6
7
8
9
POST /v7/challenge HTTP/1.1
Host: dauth-lp1.ndas.srv.nintendo.net
User-Agent: libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 13.3.0.0)
Accept: */*
X-Nintendo-PowerState: FA
Content-Length: 17
Content-Type: application/x-www-form-urlencoded

key_generation=13
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
HTTP/1.1 200 OK
Server: nginx
Date: Sun, 26 Sep 2021 19:21:43 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: strict-origin-when-cross-origin
Vary: Accept
ETag: W/"eb797bb39b7f70a033c7bbd5020bf9f0"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: b1afb7d0-b6d9-4eff-8561-0159c97cdf58
X-Runtime: 0.009675
X-Nintendo-Used-Directive: global auth
X-Nintendo-Request-Host-Header: dauth-lp1.ndas.srv.nintendo.net
X-Nintendo-Request-SNI: dauth-lp1.ndas.srv.nintendo.net

{"challenge":"mtAvqNqzYSoCEixxL_rjWoHfdDjAH51h5XcKZ6ksq2s=","data":"1OikFLkHptkhDpqy7VHb3g=="}

Then, one can obtain a device token:

1
2
3
4
5
6
7
8
9
POST /v7/device_auth_token HTTP/1.1
Host: dauth-lp1.ndas.srv.nintendo.net
User-Agent: libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 13.3.0.0)
Accept: */*
X-Nintendo-PowerState: FA
Content-Length: 211
Content-Type: application/x-www-form-urlencoded

challenge=mtAvqNqzYSoCEixxL_rjWoHfdDjAH51h5XcKZ6ksq2s=&client_id=8f849b5d34778d8e&ist=false&key_generation=13&system_version=CusHY#000d0000#r1xneESd4PiTRYIhVIl0bK1ST5L5BUmv_uGPLqc4PPo=&mac=AW9LE1TSN0xrzY1FfHHXwg
1
2
3
4
5
6
7
8
9
10
11
12
HTTP/1.1 200 OK
Server: nginx
Date: Sun, 26 Sep 2021 19:21:43 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
...
X-Nintendo-Used-Directive: global auth
X-Nintendo-Request-Host-Header: dauth-lp1.ndas.srv.nintendo.net
X-Nintendo-Request-SNI: dauth-lp1.ndas.srv.nintendo.net

{"expires_in":86400,"device_auth_token":"eyJqa3UiOiJodHRwczovL2RjZXJ0LWxwMS5uZGFzLnNydi5uaW50ZW5kby5uZXQva2V5cyIsImtpZCI6IjM2NzllMTg4LTI5ZWUtNDE4Zi04ZDkwLWI3MjRjYzg1MzQ0MSIsInR5cCI6IkpXVCIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiI2ODMzN2FjYTI4ODE1Y2JiIiwiaXNzIjoiZGF1dGgtbHAxLm5kYXMuc3J2Lm5pbnRlbmRvLm5ldCIsImF1ZCI6IjhmODQ5YjVkMzQ3NzhkOGUiLCJleHAiOjE2MzI3NjMzMDEsImlhdCI6MTYzMjY3NjkwMSwianRpIjoiZTU5YTBiMGUtOTRlMS00NGFhLWI1ZGItMGZjMGNmNTAyYWRhIiwibmludGVuZG8iOnsic24iOiJYQVcxMDAxMjM0NTY3OCIsInBjIjoiSEFDIiwiZHQiOiJOWCBQcm9kIDEiLCJpc3QiOmZhbHNlfX0.Mdl42B_tWnQQZkpp0qkvEwpkAFGos1YQ8OBKDr_rJCQlNVZLrP6_sd53U8kvwI6TWbnuxFtNxcVJh21kbbY23WsjwQN9Ph2pbjEmneov5b5SfAjWSvfEqt_ViKFQVLv_MZZXQpBYZSQmJ3sA-BbOjeEO6JI5XI3_KR0uj9IxSH_LNSiEwMMNLkP0PcC3gO5cSKcmnb1NPW2BMMdlKOSIbxDSWE4sEuYt2Pl_u2F6hVMVeoC-4z43lIv2tv7aF9Pwv-D7MR-mOxQaxYVHw2Ux4FL0zPZOJMU6qPgfzACeItd6H_A4OBMKSQwBl4DEbSwdle5tph-ur01K91FhXhI6BA"}

Or an edge token:

1
2
3
4
5
6
7
8
9
POST /v7/edge_token HTTP/1.1
Host: dauth-dd1.ndas.srv.nintendo.net
User-Agent: libcurl (nnDauth; 16f4553f-9eee-4e39-9b61-59bc7c99b7c8; SDK 13.3.0.0)
Accept: */*
X-Nintendo-PowerState: FA
Content-Length: 228
Content-Type: application/x-www-form-urlencoded

challenge=mtAvqNqzYSoCEixxL_rjWoHfdDjAH51h5XcKZ6ksq2s=&client_id=67bf9945b45248c6&ist=false&key_generation=13&system_version=CusHY#000d0000#r1xneESd4PiTRYIhVIl0bK1ST5L5BUmv_uGPLqc4PPo=&vendor_id=akamai&mac=8HKiiCC5Zqp3zxut8sSWZw
1
2
3
4
5
6
7
8
9
10
11
12
HTTP/1.1 200 OK
Server: nginx
Date: Sun, 26 Sep 2021 19:21:43 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
...
X-Nintendo-Used-Directive: global auth
X-Nintendo-Request-Host-Header: dauth-dd1.ndas.srv.nintendo.net
X-Nintendo-Request-SNI: dauth-dd1.ndas.srv.nintendo.net

{"expires_in":86400,"dtoken":"exp=1632763301~acl=%2F%2A~data=sub=68337aca28815cbb.sn=XAW10012345678.id=a73ff2b9-e772-4dc6-a01e-0861227bd202~hmac=bb7c0f27edddeb50777ec6a2fba6deacd8b8fc04faeaaaa864027c54767dea6c"}

Example of an error response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
HTTP/1.1 400 Bad Request
Server: nginx
Date: Sun, 26 Sep 2021 19:21:43 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: strict-origin-when-cross-origin
Vary: Accept
Cache-Control: no-cache
X-Request-Id: 84a8a661-a312-480a-b389-35cf83106b51
X-Runtime: 0.007699

{"errors":[{"code":"0014","message":"Invalid parameter in request."}]}
Contents