Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bna restore: bna.http.HTTPError: mobile-service.blizzard.com returned status 502 #38

Open
mx03 opened this issue Jul 18, 2023 · 99 comments

Comments

@mx03
Copy link

mx03 commented Jul 18, 2023

Is this project still supported? Not sure how much you can do if the battlenet endpoints got changed, but maybe someone has an idea.

Traceback (most recent call last):
  File "/home/maximilian/.local/bin/bna", line 8, in <module>
    sys.exit(main())
  File "/home/maximilian/.local/lib/python3.8/site-packages/click/core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "/home/maximilian/.local/lib/python3.8/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "/home/maximilian/.local/lib/python3.8/site-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/maximilian/.local/lib/python3.8/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/maximilian/.local/lib/python3.8/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "/home/maximilian/.local/lib/python3.8/site-packages/click/decorators.py", line 26, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/home/maximilian/.local/lib/python3.8/site-packages/bna/cli.py", line 222, in restore
    secret = bna.restore(serial, restore_code)
  File "/home/maximilian/.local/lib/python3.8/site-packages/bna/http.py", line 129, in restore
    challenge = client.initiate_paper_restore(serial)
  File "/home/maximilian/.local/lib/python3.8/site-packages/bna/http.py", line 48, in initiate_paper_restore
    response = self.post("/enrollment/initiatePaperRestore.htm", data=serial)
  File "/home/maximilian/.local/lib/python3.8/site-packages/bna/http.py", line 32, in post
    raise HTTPError(
bna.http.HTTPError: mobile-service.blizzard.com returned status 502
@jleclanche
Copy link
Owner

If you want to fix it and submit a patch I will review and merge it, but in general I don't have a way of actively maintaining it.

@J4bber
Copy link

J4bber commented Jul 20, 2023

I am guessing the overall method for api is different now so not working... Its been 10 years since I worked with python, so I'll just use the ios authenticator.

@mx03
Copy link
Author

mx03 commented Jul 20, 2023

Yes as blizzard deprecated the battlenet authenticator and replaced it with battlenet messenger with authenticator included, they changed probably the api endpoints. I already looked a little bit how the new works but didn't find something.

@mx03
Copy link
Author

mx03 commented Jul 23, 2023

I tracked the dns requests and found the domain authenticator-rest-api.bnet-identity.blizzard.net that has an swagger ui:
https://authenticator-rest-api.bnet-identity.blizzard.net/swagger-ui/

(Dont know why blizz has that documentation online because i don't think they want third party implementations)

https://authenticator-rest-api.bnet-identity.blizzard.net/v1/authenticator/device deviceSecret is the secret as hex.

Biggest issue is that you need an oauth 2.0 with a specific scope that probably not avail with this way: https://develop.battle.net/documentation/guides/using-oauth

@alvinpeters
Copy link

ix it possible to get that scope by snooping in the app binary or something?

@mx03
Copy link
Author

mx03 commented Jul 27, 2023

The scope is auth.authenticator (you can see it on the swagger page if you press the authorize button), i dont have much time at the moment, so i don't look further into the oauth auth with this scope.

@alvinpeters
Copy link

alvinpeters commented Jul 27, 2023

Now this gets my interest. I'm writing a simple Rust binary for this. (i hate installing fuckloads of libraries lol) Hopefully done this weekend if I don't hit any roadblocks.

@alvinpeters
Copy link

alvinpeters commented Jul 30, 2023

Yup. Turns out you can't just ask for auth.authenticator scope and be granted that. I tried authenticating with various scopes plus that scope but turns out directly asking for auth.authenticator as some random app is just impossible, it gets silently blocked. I tried entering the access token into the authenticator swagger, no joy saying "must-revalidate" after trying out one of the urls.

This is what I got from redirecting to the swagger

auth error{"error":"invalid_client","error_description":"Unauthorized grant type: implicit","state":"random state token lol"

We need another approach for this. Maybe even some gray area methods by trying to get the Battle.net app info. For now, I can try sniffing the REST GETs and POSTs of the app with wireshark androiddump and see if there's something that can be useful.

@mx03
Copy link
Author

mx03 commented Jul 30, 2023

The api works with the extracted devicekey from the battlenet app. So yes thats the way it should work.

@alvinpeters
Copy link

The api works with the extracted devicekey from the battlenet app. So yes thats the way it should work.

@mx03 how do you extract the devicekey? and also we need a way to either distribute the key (kinda grey area legal) or provide a way for people to reliably extract the device key.

Once done, I can finish my implementation within a few days.

@mx03
Copy link
Author

mx03 commented Jul 30, 2023

Sorry i meant the client id, its stored on a android device in this file under com.blizzard.messenger.PREF_AUTHENTICATION_PROVIDER_CLIENT_ID and is custom for every user /data/data/com.blizzard.messenger/shared_prefs/com.blizzard.messenger.authenticator_preferences.xml

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="com.blizzard.messenger.AUTHENTICATOR_CREDENTIALS_ENCRYPTION_TYPE">AES</string>
    <boolean name="com.blizzard.messenger.AUTHENTICATOR_SETUP_POSTPONE_LOGIN" value="false" />
    <string name="com.blizzard.messenger.AUTHENTICATOR_RESTORE_CODE">Y</string>
    <string name="com.blizzard.messenger.PREF_AUTHENTICATION_PROVIDER_CLIENT_ID">C</string>
    <string name="com.blizzard.messenger.AUTHENTICATOR_DEVICE_SECRET">X </string>
    <string name="com.blizzard.messenger.PREF_AUTHENTICATION_PROVIDER_HOST_URL">oauth.battle.net</string>
    <string name="com.blizzard.messenger.AUTHENTICATOR_BGS_REGION_CODE">EU</string>
    <string name="com.blizzard.messenger.AUTHENTICATOR_SERIAL">R</string>
    <long name="com.blizzard.messenger.AUTHENTICATOR_SERVER_TIME_DIFF" value="0" />
</map>

@alvinpeters
Copy link

alvinpeters commented Jul 30, 2023

LOL IT FUCKING WORKED HAHAHAHAHA THANK YOU SO MUCH @mx03

Sadly that forces everyone to download the app and login once before getting the client ID. Are you actually sure about the client ID being per-user? I'm gonna test with different accounts later if you haven't tried that. And would non-rooted users be able to access that directory?

For those waiting for an app to automate these steps. (only slightly due to the way of getting the client ID/device secret) This is what I did:

  1. Download the Battle.net Messenger
  2. Login to the app
  3. (This step might need root) Get the secret:
  • From the app
    1. Press "Enable now" when prompted to enable the authenticator
    2. Go to /data/data/com.blizzard.messenger/shared_prefs/com.blizzard.messenger.authenticator_preferences.xml
    3. Either copy the file to the PC or open it in the phone
    4. Save the content of the string tag named "com.blizzard.messenger.AUTHENTICATOR_DEVICE_SECRET"
  • From the REST API
    1. Go to /data/data/com.blizzard.messenger/shared_prefs/com.blizzard.messenger.authenticator_preferences.xml
    2. Either copy the file to the PC or open it in the phone
    3. Copy the content of the string tag named com.blizzard.messenger.PREF_AUTHENTICATION_PROVIDER_CLIENT_ID
    4. Go to https://authenticator-rest-api.bnet-identity.blizzard.net/webjars/swagger-ui/index.html

    You can skip all the steps above with this client ID (as long as this doesn't get changed lol): baedda12fe054e4abdfc3ad7bdea970a

    1. Make sure to tick the 'auth.authenticator' scope then click "Authorize," paste the acquired client ID to the client ID input then click "Authorize."
    2. Login if you are not logged in already. Either way, you should be redirected back and see the client ID input as just client_id: ******
    3. Click the "POST: Click and add a brand new authenticator..." header, click "Try it out," then "Execute."
    4. The response should be "200: OK" with a JSON output providing your device secret
    5. Save the value of deviceSecret and might as well save serial and restoreCode for backup
  1. Convert the device secret from hex to base32. On Linux and maybe macOS, this can be done with echo "PASTEYOURDEVICESECRETHERE" | xxd -r -p | base32
  2. Put the converted secret and set the digits to 8 on your authenticator of your choosing. I use Aegis and it works.

@alvinpeters
Copy link

Maybe there is an API that allows us to grab a custom per user client ID like the app but that's highly improbable.

@mx03
Copy link
Author

mx03 commented Jul 30, 2023

As the app has certificate pinning i haven't the time for look into more details, but it shouldn't be hard to make an oauth auth like the app and get the client id.

@alvinpeters
Copy link

@mx03 does your client id start and end with 'b' and 'a' respectively? Because if so, the client ID is the same everywhere. I tried with two accounts and it is the same. Just wondering if it's also the same on all devices.

Just wondering because maybe we can just distribute the client ID since it's hard/impossible for people without rooted phones to get the client ID anyways.

@mx03
Copy link
Author

mx03 commented Jul 31, 2023

@mx03 does your client id start and end with 'b' and 'a' respectively? Because if so, the client ID is the same everywhere. I tried with two accounts and it is the same. Just wondering if it's also the same on all devices.

Just wondering because maybe we can just distribute the client ID since it's hard/impossible for people without rooted phones to get the client ID anyways.

Yes start with b and ending with a. So it seems it is the same. Just thought about oauth and yes the client id is no secret https://www.oauth.com/oauth2-servers/client-registration/client-id-secret/ . Just half year ago i implemented oauth myself just forget the naming and the use of the clientid.

@alvinpeters
Copy link

alvinpeters commented Jul 31, 2023

Reckoned I'm backed into a corner on this one. The localhost redirects are not whitelisted for this client ID and only allows redirect to the Swagger UI (https://authenticator-rest-api.bnet-identity.blizzard.net/swagger-ui/oauth2-redirect.html) and probably the localhost address pointing to the messenger. I'm wondering how do Android apps implement OAuth2 with just a client ID then redirect to the device's web viewer/bowser? Snipping full HTTPS URLs is impossible so the only way to figure this out is by trying to reverse engineer it lol

So ye, it's kinda pointless even to make an app for this if you can't ask for an oauth2 token from the device with the client ID provided. I'm putting the client ID of the Battle.net Messenger baedda12fe054e4abdfc3ad7bdea970a so everyone can make use of it above

Screenshot_20230801-085240.png

@mx03
Copy link
Author

mx03 commented Aug 1, 2023

Yes this way probably only works with an electron app that can fetch the token from the returning url.

The android app itself does this login request https://account.battle.net/login?sdkVersion=masdk/7.2.1&code_verifier=[XXX]&deviceId=[XXX]&clientVersion=1.19.2.7&continuation-type=NATIVE_HANDOFF&flowTrackingId=[XXX]&app=BSAp&ca&ref=blizzard-social%3A%2F%2Flocalhost%3A0%2F but that url blizzard-social://localhost:0/ still dont work directly with the authenticator-rest api.

The response url is blizzard-social://localhost:0/?ST=[XXX]&STT=enc&accountId=[XXX]&flowTrackingId=[XXX]&flow_type=hard_account_login.

@lightmaster
Copy link

@striczkof Think the clientid might have changed, as I just tried this and get back 403: Forbidden..... The request requires higher privileges than provided by the access token. Gonna hunt down an old Android phone that's rooted so I can get the /data file to check the new clientid

@alvinpeters
Copy link

alvinpeters commented Aug 3, 2023

@striczkof Think the clientid might have changed, as I just tried this and get back 403: Forbidden..... The request requires higher privileges than provided by the access token. Gonna hunt down an old Android phone that's rooted so I can get the /data file to check the new clientid

@lightmaster Did you tick the "auth.authenticator" scope before trying to login? think I might have forgotten to add that in instructions.

@alvinpeters
Copy link

@lightmaster Oh ye I did forget 💀

@lightmaster
Copy link

90% sure I did, but I'll run it again to make sure

@lightmaster
Copy link

I was wrong, apparently I didn't tick that box. Got serial, restorecode, and secret back. Thx

@BlastBolt5
Copy link

@striczkof thank you so much for solving this, finally can have totp in bitwarden for blizzard

@Drudoo
Copy link

Drudoo commented Sep 5, 2023

I did @striczkof described (using the above device ID) but whenever i try and attach the converted device secret to a password manager (tried 1password and MS Authenticator) i only get 6 digit codes, which are then not accepted by the BN client.

EDIT: Nevermind. I created the QR code wrong. Works in 1Password now.

@TXort
Copy link

TXort commented Sep 13, 2023

I managed to get the AUTHENTICATOR_DEVICE_SECRET string from a rooted phone method, but I could not figure out what to do next and could not get it working by trial and error. For me AUTHENTICATOR_DEVICE_SECRET are 2 base64 strings separated by comma with length 64 and 24. What am I doing wrong?

@vmoffset
Copy link

vmoffset commented Sep 27, 2023

I managed to get the AUTHENTICATOR_DEVICE_SECRET string from a rooted phone method, but I could not figure out what to do next and could not get it working by trial and error. For me AUTHENTICATOR_DEVICE_SECRET are 2 base64 strings separated by comma with length 64 and 24. What am I doing wrong?

Same here, the API method seems to be patched when going to the swagger-ui:

{"errorCode":"BLZBNTARA10000000","message":"An unknown server error occurred."}

So the root method is the only option, I got the XML however its all bytes I believe after base64 decoding it.
Hoping someone can figure this out, maybe @mx03

@alvinpeters
Copy link

alvinpeters commented Sep 27, 2023

I managed to get the AUTHENTICATOR_DEVICE_SECRET string from a rooted phone method, but I could not figure out what to do next and could not get it working by trial and error. For me AUTHENTICATOR_DEVICE_SECRET are 2 base64 strings separated by comma with length 64 and 24. What am I doing wrong?

Same here, the API method seems to be patched when going to the swagger-ui:

{"errorCode":"BLZBNTARA10000000","message":"An unknown server error occurred."}

So the root method is the only option, I got the XML however its all bytes I believe after base64 decoding it. Hoping someone can figure this out, maybe @mx03

LOL

I thought the same too, but apparently, they did not get rid of it. They just changed the URL to https://authenticator-rest-api.bnet-identity.blizzard.net/webjars/swagger-ui/index.html (redirect from https://authenticator-rest-api.bnet-identity.blizzard.net/) and the client ID still works somehow. (tried getting my serial and restore and it works)
Still invalid callback for localhost so can't make a client for this one :/

As for the device secret, they probably changed its format. I gotta check when I have free time.

@ldehaas1612
Copy link

LOL IT FUCKING WORKED HAHAHAHAHA THANK YOU SO MUCH @mx03

Sadly that forces everyone to download the app and login once before getting the client ID. Are you actually sure about the client ID being per-user? I'm gonna test with different accounts later if you haven't tried that. And would non-rooted users be able to access that directory?

For those waiting for an app to automate these steps. (only slightly due to the way of getting the client ID/device secret) This is what I did:

  1. Download the Battle.net Messenger
  2. Login to the app
  3. (This step might need root) Get the secret:
  • From the app

    1. Press "Enable now" when prompted to enable the authenticator
    2. Go to /data/data/com.blizzard.messenger/shared_prefs/com.blizzard.messenger.authenticator_preferences.xml
    3. Either copy the file to the PC or open it in the phone
    4. Save the content of the string tag named "com.blizzard.messenger.AUTHENTICATOR_DEVICE_SECRET"
  • From the REST API

    1. Go to /data/data/com.blizzard.messenger/shared_prefs/com.blizzard.messenger.authenticator_preferences.xml
    2. Either copy the file to the PC or open it in the phone
    3. Copy the content of the string tag named com.blizzard.messenger.PREF_AUTHENTICATION_PROVIDER_CLIENT_ID
    4. Go to https://authenticator-rest-api.bnet-identity.blizzard.net/webjars/swagger-ui/index.html

    You can skip all the steps above with this client ID (as long as this doesn't get changed lol): baedda12fe054e4abdfc3ad7bdea970a

    1. Make sure to tick the 'auth.authenticator' scope then click "Authorize," paste the acquired client ID to the client ID input then click "Authorize."
    2. Login if you are not logged in already. Either way, you should be redirected back and see the client ID input as just client_id: ******
    3. Click the "POST: Click and add a brand new authenticator..." header, click "Try it out," then "Execute."
    4. The response should be "200: OK" with a JSON output providing your device secret
    5. Save the value of deviceSecret and might as well save serial and restoreCode for backup
  1. Convert the device secret from hex to base32. On Linux and maybe macOS, this can be done with echo "PASTEYOURDEVICESECRETHERE" | xxd -r -p | base32
  2. Put the converted secret and set the digits to 8 on your authenticator of your choosing. I use Aegis and it works.

I just wanted to chip in and provide my 2 cents about this one. I followed above instructions and turns out you do not need to have the authenticator installed, do not have to use a special clientID. Just do the following to get 2fa secret:

  • Go to https://authenticator-rest-api.bnet-identity.blizzard.net/webjars/swagger-ui/index.html
  • use clientID: baedda12fe054e4abdfc3ad7bdea970a
    Make sure to tick the 'auth.authenticator' scope then click "Authorize," paste the acquired client ID to the client ID input then click "Authorize."
  • Login if you are not logged in already. Either way, you should be redirected back and see the client ID input as just client_id: ******
  • Click the "POST: /v1/authenticator - Click and add a brand new authenticator..." header, click "Try it out," then "Execute."
  • The response should be "200: OK" with a JSON output providing your device secret
    If it responds with anything other then "200: OK", read what it says and act accordingly. In my case I already had the battle.net app installed, and you cannot create a new authenticator if you do. So in that case, remove the authorization from the app and start the POST step again.
  • Save the value of deviceSecret and save serial and restoreCode as well for backup!!
  • Convert the device secret from hex to base32. On Linux and macOS use terminal. (on windows use WSL or a online tool) the command is echo "PASTEYOURDEVICESECRETHERE" | xxd -r -p | base32
  • Put the converted secret in your 2FA of choice and set the digits to 8. I used Aegis and it works perfectly.

As you can see, lots of overlap, but streamlined process. Hope this helps the next person! Thanks @mx03 and @striczkof!

@schleeb
Copy link

schleeb commented Jan 17, 2024

My apologies if this is too far off-topic, but I was able to use all the tricks that have been documented here to generate a QR code that works in Google Authenticator, but when I try to use it with Authy, I get a "Invalid format" "Token format not supported." error message. Does anyone have any ideas?
I know I've previously used python-bna to generate a code that did work in Authy, so I know it supports 8-digit codes.

@BillyCurtis
Copy link

My apologies if this is too far off-topic, but I was able to use all the tricks that have been documented here to generate a QR code that works in Google Authenticator, but when I try to use it with Authy, I get a "Invalid format" "Token format not supported." error message. Does anyone have any ideas? I know I've previously used python-bna to generate a code that did work in Authy, so I know it supports 8-digit codes.

I was able to add it to Authy by creating a QR code using qrencode -t ANSI "otpauth://totp/BattleNet:Battle.net?secret=deviceSecret&digits=8"

@schleeb
Copy link

schleeb commented Jan 18, 2024

My apologies if this is too far off-topic, but I was able to use all the tricks that have been documented here to generate a QR code that works in Google Authenticator, but when I try to use it with Authy, I get a "Invalid format" "Token format not supported." error message. Does anyone have any ideas? I know I've previously used python-bna to generate a code that did work in Authy, so I know it supports 8-digit codes.

I was able to add it to Authy by creating a QR code using qrencode -t ANSI "otpauth://totp/BattleNet:Battle.net?secret=deviceSecret&digits=8"

Thank you so much, that works!
Oddly, the command I'd been using had -t ansiutf8 which, now that I think about it, doesn't really make sense, and I'm not sure where I even found it in the first place... Regardless, though, I'm sorted out!

@forrestwparker
Copy link

For those in the Apple ecosystem with no access to Windows:

Follow the steps in this comment, but install this free app on your iPhone or iPad as an alternative to Charles Proxy. No other device needed.

@3936355
Copy link

3936355 commented Jan 19, 2024

How do I get Bearer Tokens without using Charles

@jaredm4
Copy link

jaredm4 commented Jan 20, 2024

Here's how i got it working with 1Password using Charles Proxy and the Battle.net App on my iPhone

Bummer this does not work on Android. Recent Android releases adopt a safe-by-default method for using custom CAs. Each app has to be manually configured to accept the Charles CA, which we can't do since we don't have access to the app source.

Sucks. I hate you, Blizzard.

@BillyCurtis
Copy link

Here's how i got it working with 1Password using Charles Proxy and the Battle.net App on my iPhone

Bummer this does not work on Android. Recent Android releases adopt a safe-by-default method for using custom CAs. Each app has to be manually configured to accept the Charles CA, which we can't do since we don't have access to the app source.

Sucks. I hate you, Blizzard.

I have another way of doing this without needing to use the Battle.net App. i'll post a guide later

@BillyCurtis
Copy link

Here is another way without having to use the Battle.net App

1. Retrieve SSO Token:

2. Get Bearer Token:

  • Replace <SSO_TOKEN> with the token you got from step 1 and execute the following curl command to obtain the Bearer Token:

    curl -X 'POST' \
    'https://oauth.battle.net/oauth/sso' \
    -H "content-type: application/x-www-form-urlencoded; charset=utf-8" \
    -d "client_id=baedda12fe054e4abdfc3ad7bdea970a&grant_type=client_sso&scope=auth.authenticator&token=<SSO_TOKEN>"
    • Response:
      {"access_token":"XXX","token_type":"bearer","expires_in":0,"scope":"auth.authenticator","sub":"XXX"}
  • Copy the Bearer Token to use in steps 3, 4. or 5.

3. Get Serial & Restore Codes:

  • Use the Bearer Token to fetch the Serial and Restore Codes of an existing authenticator:

    curl -X 'GET' \
    'https://authenticator-rest-api.bnet-identity.blizzard.net/v1/authenticator' \
    -H 'accept: application/json' \
    -H "Authorization: Bearer <BEARER_TOKEN>"
    • Response:
      {"Restore Code": "XXX", "Serial Number": "XXX"}

4. Get Existing Authenticator Device Secret:

  • Use the Bearer Token, Serial, and Restore codes to retrieve the Device Secret of an Existing Authenticator:

    curl -X 'POST' \
    'https://authenticator-rest-api.bnet-identity.blizzard.net/v1/authenticator/device' \
    -H 'accept: application/json' \
    -H 'Content-Type: application/json' \
    -H "Authorization: Bearer <BEARER_TOKEN>" \
    -d '{
      "restoreCode": "<RESTORE_CODE>",
      "serial": "<SERIAL>"
    }'
    • Response:
      {"serial":"XXX","restoreCode":"XXX","deviceSecret":"XXX","timeMs":0,"requireHealup":false}

5. Create and Add a New Authenticator:

  • Use the Bearer Token to create and add a new authenticator to the users account :

    curl -X 'POST' \
    'https://authenticator-rest-api.bnet-identity.blizzard.net/v1/authenticator' \
    -H 'accept: application/json' \
    -H "Authorization: Bearer <BEARER_TOKEN>" \
    -d ''
    • Response:
      {"serial":"XXX","restoreCode":"XXX","deviceSecret":"XXX","timeMs":0,"requireHealup":false}

6. Add Authenticator to Password Manager.

  • After you have obtianed the deviceSecret convert it from hex to base32 using echo "deviceSecret" | xxd -r -p | base32 on Linux/macOS or cryptii.com if on Windows

  • Replace deviceSecret in the following URL: otpauth://totp/Battle.net?secret=deviceSecret&digits=8 with the newly obtained base32 device secret, and you should have a working TOTP.

@jaredm4
Copy link

jaredm4 commented Jan 21, 2024

That works, thanks @BillyCurtis !

Notes for others:

  • helps to run step 1 in an incognito window. My existing cookies made that step fail even after a fresh login.
  • if your account currently does not have an authenticator, skip steps 3 and 4, go straight to 5.

@BuongiornoTexas
Copy link

Hi Billy,

I just tried this and died on step 2 with {"error":"invalid_token","error_description":"Invalid SSO token."}. I've tried it twice with two separate logins and SSO tokens. There seem to be a couple of places I could be going wrong.

  1. I'm using a web browser in step 1 to generate the token, and then going to a terminal shell to run the curl command in step 2 (I've been careful about copying the sso token, so I'm pretty sure this isn't the problem). Is this OK, or do I need to be generating the sso token directly from the terminal session (not my area, so not sure how this would work?).
  2. I'm getting a sso token starting with KR- for the Korean authentication server. Could this mean I need to use a different oauth uri or client id? (I think the have the correct terminology here).
  3. I do already have a sign in working with the battle.net client and have my restore code and serial - I was expecting I would be able to skip steps 3 and 5 to get everything up and running - does this sound right?

Cheers!

@L-Goncalves
Copy link

L-Goncalves commented Jan 21, 2024

Hello Everyone, I've been able to replicate the OAuth, you will need to first login into your account at account.battle.net

The open Dev Tools from the browser, go into Cookies Section and get the following value of the Cookie:

image

You will need to copy it and use in OAuth to get the bearer token to use in the Authenticator Rest API:

I've made Javascript script to do that but it can be converted to python too:

async function generateToken() {
  const headers = {
    'Host': 'account.battle.net',
    'accept': 'application/json; charset=UTF-8',
    'content-type': 'application/json; charset=UTF-8',
    'user-agent': 'Battle.net/7123 CFNetwork/1404.0.5 Darwin/22.3.0',
    'accept-language': 'en-GB,en-US;q=0.9,en;q=0.8',
  };

  const url = 'https://account.battle.net/login/sso/generate';

  const data = {
    program_id: 'BSAp',
    platform_id: 'ios',
    client_version: 1,
    login_ticket: '[BA-tassadar COOKIE USE IT HERE]'
  };

  const options = {
    method: 'POST',
    headers: headers,
    body: JSON.stringify(data),
  };

  try {
    const response = await fetch(url, options);
    const dataResponse = await response.json();
    return await oauth(dataResponse.authentication_token);
  } catch (error) {
    console.error(error);
    throw error; // Rethrow the error to propagate it up
  }
}

async function oauth(generated_token) {
  const headers = {
    'Host': 'oauth.battle.net',
    'accept': '*/*',
    'content-type': 'application/x-www-form-urlencoded; charset=utf-8',
    'user-agent': 'BlizzardSocial/1.24.2 (com.blizzard.social; build:7123; iOS 16.3.1) Alamofire/5.8.0',
    'accept-language': 'en-BR;q=1.0, pt-BR;q=0.9',
  };

  const url = 'https://oauth.battle.net/oauth/sso';

  const data = {
    client_id: 'baedda12fe054e4abdfc3ad7bdea970a',
    grant_type: 'client_sso',
    scope: 'auth.authenticator',
    token: generated_token
  };

  const body = new URLSearchParams(data);

  const options = {
    method: 'POST',
    headers: headers,
    body: body,
  };

  try {
    const response = await fetch(url, options);
    return await response.json();
  } catch (error) {
    console.error(error);
    throw error; // Rethrow the error to propagate it up
  }
}

These 2 Functions are used to generate the SSO Token and the other one retrives the Bearer Token to use it then after having the bearer token you are free to use in the request for the rest api like that:

async function fetchAuthenticatorData(bearerToken) {
  const url = 'https://authenticator-rest-api.bnet-identity.blizzard.net/v1/authenticator';

  const headers = {
    'Host': 'authenticator-rest-api.bnet-identity.blizzard.net',
    'accept': '*/*',
    'user-agent': 'BlizzardSocial/1.24.2 (com.blizzard.social; build:7123; iOS 16.3.1) Alamofire/5.8.0',
    'accept-language': 'en-BR;q=1.0, pt-BR;q=0.9',
    'authorization': `Bearer ${bearerToken}`,
    'Content-Type': 'application/json',
  };

  const options = {
    method: 'POST',
    headers: headers,
  };

  try {
    const response = await fetch(url, options);
    return await response.json();
  } catch (error) {
    console.error(error);
    throw error;
  }
}

@MotorkinR12P
Copy link

MotorkinR12P commented Jan 21, 2024

2. Get Bearer Token:

* Replace `<SSO_TOKEN>` with the token you got from step 1 and execute the following curl command to obtain the Bearer Token:

hello, I also have problems with step 2, i'm running it on windows 11, cmd as administrator
1

EDIT: problem fixed, it was because of the syntax in Windows

@BuongiornoTexas
Copy link

Resolved my problem. In step 1, I grabbed the sso token at the 404 page. However, it changed between this page and the account overview. My success path was:

  1. Login on a web browser, get to my account page and then extract the BA-tassadar value (thanks @L-Goncalves).

  2. Use @BillyCurtis step 2 for the bearer token and step 4 for the device secret (I already had the recovery code and serial info).

Thank you to all of the thread contributors - much appreciated.

@BillyCurtis
Copy link

Resolved my problem. In step 1, I grabbed the sso token at the 404 page. However, it changed between this page and the account overview. My success path was:

  1. Login on a web browser, get to my account page and then extract the BA-tassadar value (thanks @L-Goncalves).
  2. Use @BillyCurtis step 2 for the bearer token and step 4 for the device secret (I already had the recovery code and serial info).

Thank you to all of the thread contributors - much appreciated.

Using the SSO token from the 404 page URL should work without having to get it from the BA-tassadar value.

@BuongiornoTexas
Copy link

Using the SSO token from the 404 page URL should work without having to get it from the BA-tassadar value.

I thought so too, but it failed several times for me using the token from the 404 page. I've just rechecked, and the BA-tassadar value is different from the token value on the 404 page and the account page (same value both times). On Windows this time.

So I'm not sure what is different for me? Maybe firefox, maybe the fact that I already have the Blizzard authenticator setup and I'm just trying to recover the devicesecret?

Regardless, I thought I would share as it may provide a resolution for others.

@GlassedSilver
Copy link

For anyone unable to locate the SSO Token in step one you may already have the authenticator added like me (for the sweet sweet push notification approval). In that case you need to go to the Security Section of your Account page and select Get Restore Code.

Then open dev tools and find the required token as described.

This thread should be made into a wiki if you ask me.

@lightmaster
Copy link

Blizzard killed my 2fa cuz I still had an old version of their authenticator authorized. Trying @BillyCurtis's steps, and I get the SSO-token and the bearer token, but when I try to add a new authenticator, I get this response:

{"url":"https://account.battle.net/creation/","requireHealup":true}% 

@L-Goncalves
Copy link

Blizzard killed my 2fa cuz I still had an old version of their authenticator authorized. Trying @BillyCurtis's steps, and I get the SSO-token and the bearer token, but when I try to add a new authenticator, I get this response:

{"url":"https://account.battle.net/creation/","requireHealup":true}% 

I believe that the requireHealup value is if it needs a phone number, usually when I was attaching authenticators I would get that if no phone number was attached to the account.

@ldehaas1612
Copy link

Blizzard killed my 2fa cuz I still had an old version of their authenticator authorized. Trying @BillyCurtis's steps, and I get the SSO-token and the bearer token, but when I try to add a new authenticator, I get this response:

{"url":"https://account.battle.net/creation/","requireHealup":true}% 

Read carefully.. You have to specify an phone number to your account in order to create a 2FA. This is their fallback method

@lightmaster
Copy link

lightmaster commented Feb 12, 2024

@ldehaas1612 @L-Goncalves Just found that when reading all the messages since last time I had to do this dance with Blizzard. Today I had just looked at the most recent set of instructions and didn't realize there had to be a phone number on the account. Also, I definitely had a phone number on it before cuz the verification message when I just added my number showed the last time they sent verification to my number. Not sure why they removed my number at some point.

EDIT: It worked now, thanks.

@stjeffrey
Copy link

Trying to follow @BillyCurtis's method and it fails for me at step 3
{"errorCode":"BLZBNTARA10000303","message":"Failed to retrieve authenticator; authenticator not found."}%

Can someone confirm if this method still works?

@BillyCurtis
Copy link

Trying to follow @BillyCurtis's method and it fails for me at step 3 {"errorCode":"BLZBNTARA10000303","message":"Failed to retrieve authenticator; authenticator not found."}%

Can someone confirm if this method still works?

Go straight to step 5 after you get the bearer token if you don’t already have an authenticator

@wpeii
Copy link

wpeii commented Feb 24, 2024

2. Get Bearer Token:

* Replace `<SSO_TOKEN>` with the token you got from step 1 and execute the following curl command to obtain the Bearer Token:

hello, I also have problems with step 2, i'm running it on windows 11, cmd as administrator 1

EDIT: problem fixed, it was because of the syntax in Windows

I'm getting this error too. Can you please share the fixed command you used?

@ningmeng52022
Copy link

Here's how i got it working with 1Password using Charles Proxy and the Battle.net App on my iPhone

Bummer this does not work on Android. Recent Android releases adopt a safe-by-default method for using custom CAs. Each app has to be manually configured to accept the Charles CA, which we can't do since we don't have access to the app source.

Sucks. I hate you, Blizzard.

Thank you, I have successfully obtained the device secret following your tutorial.

@ciphersimian
Copy link

I'm pleased to report that @BillyCurtis's refined steps here:

#38 (comment)

still work like a charm!

I received the dreaded e-mail today that my legacy authenticator was removed from my account so I had no authenticator, and they also reset my password. I followed the password reset e-mail, logged in, did step 1 & 2, skipped to step 5 and everything went perfectly. I was able to logout and back in, was prompted for the auth code, and the andOTP worked using:

Type TOTP
Issuer Battle.net
Label Battle.net
Secret <base32 device secret from step 5 above>
Period 30
Digits 8
Algorithm SHA1

Thanks to everyone who contributed here!

@Gigafrost
Copy link

#38 (comment)
by @BillyCurtis and #38 (comment) by @L-Goncalves Also still works for me as well! With some slight alterations

So what worked for me was first following steps to get the Bearer token from #38 (comment) by @L-Goncalves

I only needed the first code but had to convert it to python because I didn't know how to run it properly as a js file. Here's my python version of the code which seemed to work:

import requests

def generate_token():
    headers = {
        'Host': 'account.battle.net',
        'accept': 'application/json; charset=UTF-8',
        'content-type': 'application/json; charset=UTF-8',
        'user-agent': 'Battle.net/7123 CFNetwork/1404.0.5 Darwin/22.3.0',
        'accept-language': 'en-GB,en-US;q=0.9,en;q=0.8',
    }

    url = 'https://account.battle.net/login/sso/generate'

    data = {
        'program_id': 'BSAp',
        'platform_id': 'ios',
        'client_version': 1,
        'login_ticket': '[BA-tassadar COOKIE USE IT HERE]'
    }

    try:
        response = requests.post(url, headers=headers, json=data)
        response.raise_for_status()
        data_response = response.json()
        return oauth(data_response['authentication_token'])
    except requests.exceptions.RequestException as error:
        print(error)
        raise

def oauth(generated_token):
    headers = {
        'Host': 'oauth.battle.net',
        'accept': '*/*',
        'content-type': 'application/x-www-form-urlencoded; charset=utf-8',
        'user-agent': 'BlizzardSocial/1.24.2 (com.blizzard.social; build:7123; iOS 16.3.1) Alamofire/5.8.0',
        'accept-language': 'en-BR;q=1.0, pt-BR;q=0.9',
    }

    url = 'https://oauth.battle.net/oauth/sso'

    data = {
        'client_id': 'baedda12fe054e4abdfc3ad7bdea970a',
        'grant_type': 'client_sso',
        'scope': 'auth.authenticator',
        'token': generated_token
    }

    try:
        response = requests.post(url, headers=headers, data=data)
        response.raise_for_status()
        return response.json()
    except requests.exceptions.RequestException as error:
        print(error)
        raise

# Usage
try:
    token = generate_token()
    print('Bearer Token:', token)
except Exception as error:
    print('An error occurred:', error)

Then I followed @BillyCurtis 's tutorial from there, but for me the formatting of the curl commands didn't work on my end, so I figured out that I had to remove the backslashes and change the single quotes to double quotes, then making it all a single line

So for example his first curl command

curl -X 'POST' \
'https://oauth.battle.net/oauth/sso' \
-H "content-type: application/x-www-form-urlencoded; charset=utf-8" \
-d "client_id=baedda12fe054e4abdfc3ad7bdea970a&grant_type=client_sso&scope=auth.authenticator&token=<SSO_TOKEN>"

was changed to this:

curl -X "POST" "https://oauth.battle.net/oauth/sso" -H "content-type: application/x-www-form-urlencoded; charset=utf-8" -d "client_id=baedda12fe054e4abdfc3ad7bdea970a&grant_type=client_sso&scope=auth.authenticator&token=<SSO_TOKEN>"

Which then worked.
Also learned that for 1password you can add it via editing the URL > +add more button > then One-Time password

image

And pasting your entire otpauth URL right in that field and hitting save

Took a bit to figure out but now it works great!~ Thanks so much guys for helping us with this!

@Ed1123
Copy link

Ed1123 commented Sep 10, 2024

Thanks to #38 (comment)
Just a couple of notes of things I had to do:

  • I had to replace double quotes
  • Install coreutils (brew install coreutils) in Mac OS for base32 to work.
  • Installed qrencode (brew install qrencode) to build a QR code. I used this to show it in the terminal qrencode -t ansiutf8 "otpauth://totp/Battle.net?secret=deviceSecretBase32&digits=8"
  • Use Aegis to read the QR instead of my Authy since Authy does not support the URL (maybe because of the 8 digits).

When I came back to the tab where I was login I had to login again. It asked me for the auth code. Used the one in Aegis and worked like a champ!

@wpeii
Copy link

wpeii commented Sep 25, 2024

Hello everyone. Thanks to @BillyCurtis and @Gigafrost, I made it too! I have wrapped up both their methods, tested, and rewrote them for people who still are facing issues. Here is my guide on how to attach an authenticator to a Battle.net account.

Before Starting...

  1. This guide is only made for attaching a new authenticator.
  2. I have only tested this on a Windows machine.
  3. Everything here is based on my own results, and may differ for you.

Perquisites

  1. Have a phone number linked to your Battle.net account.
  2. Check if you have an attached authenticator to your Battle.net account and go ahead detaching it by going to account.battle.net > Security > Battle.net Authenticator - click "Detach" > and confirm by clicking "Detach" again. If you do not have an attached authenticator, skip this and go to Step 1.

Step 1. Retrieve SSO Token

  • Go to account.battle.net/login/en/?ref=localhost. Log in, and ignore the "404" error. From the URL bar, look for the "ST=" entry and copy the SSO token following it.
    • This is how the SSO Token should look like: EU-u33pyxqgx5l73zu936oujss6mabeyhry-1177987422 or US-u33pyxqgx5l73zu936oujss6mabeyhry-1177987422
    • The token starts with either "EU" or "US" depending from which country you logged in from.
    • If you received an error with the SSO Token in steps to follow, use a VPN to change the beginning format of the token. For example, if you received an error with an SSO Token that starts with "EU", then use a VPN to route your connection to the United States (make sure that you are at us.account.battle.net/login/en/?ref=localhost (or eu.account.battle.net/login/en/?ref=localhost if you are routing your connection from the United States to an EU country)) and retry Step 1 to retrieve an SSO Token that starts with "US" (or "EU"). This will not affect your Battle.net account region/payments/pricings or any similar settings and is intended for the authenticator only.

Step 2. Get Bearer Token

  • Replace <SSO_TOKEN> with the SSO Token you retrieved from Step 1 in the following command and execute it to obtain the Bearer Token.
  • Open CMD.
    • Run:
       curl -X "POST" "https://oauth.battle.net/oauth/sso" -H "content-type: application/x-www-form-urlencoded; charset=utf-8" -d "client_id=baedda12fe054e4abdfc3ad7bdea970a&grant_type=client_sso&scope=auth.authenticator&token=<SSO_TOKEN>"
      
      • Response that you should be getting:
        {"access_token":"XXX","token_type":"bearer","expires_in":0,"scope":"auth.authenticator","sub":"XXX"}
  • Save the response somewhere safe, keep CMD open, and go ahead to Step 3.

Step 3. Attach a New Authenticator

  • Replace <BREARER_TOKEN> with the Bearer Token you retrieved from Step 2 in the following command and execute it to attach an authenticator to your Battle.net account and obtain Device Secret.
    • Run:
       curl -X "POST" "https://authenticator-rest-api.bnet-identity.blizzard.net/v1/authenticator" -H "accept: application/json" -H "Authorization: Bearer <BEARER_TOKEN>"
      
      • Response that you should be getting:
        {"serial":"XXX","restoreCode":"XXX","deviceSecret":"XXX","timeMs":0,"requireHealup":false}
  • Now you have successfully attached an authenticator to your Battle.net account.
  • Save the response somewhere safe too and read Additional Notes below.

Additional Notes

  • Save both responses from Step 2 and Step 3 somewhere safe. Do NOT save it in your password manager as it may cause a security risk. Treat them like backup/recovery credentials. Feel free to save SSO Token too.
  • You can close CMD now.

Step 4. Setup the Attached Authenticator to a TOTP URL

  • After you have obtained deviceSecret, convert it from hex to base32 using cryptii.com/pipes/hex-to-base32.
  • Place deviceSecret with the following TOTP URL with the newly obtained Device Secret, and you should have a working TOTP URL.
    • otpauth://totp/Battle.net?secret=deviceSecret&digits=8
  • Lastly, paste the TOTP to an authenticator app or a password manager that supports TOTP.

Credits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests