| 528 | } |
| 529 | |
| 530 | void OAuthService::ParseTokenResponse(std::string_view body, |
| 531 | AuthSuccessCallback successCallback, |
| 532 | AuthFailureCallback failureCallback, |
| 533 | AudiocomTrace trace, |
| 534 | bool silent) |
| 535 | { |
| 536 | rapidjson::Document document; |
| 537 | document.Parse(body.data(), body.size()); |
| 538 | |
| 539 | if (!document.IsObject()) |
| 540 | { |
| 541 | if (failureCallback) |
| 542 | failureCallback(200, body); |
| 543 | |
| 544 | SafePublish({ {}, body, trace, false, silent }); |
| 545 | return; |
| 546 | } |
| 547 | |
| 548 | const auto tokenType = document["token_type"].GetString(); |
| 549 | const auto accessToken = document["access_token"].GetString(); |
| 550 | const auto expiresIn = document["expires_in"].GetInt64(); |
| 551 | const auto newRefreshToken = document["refresh_token"].GetString(); |
| 552 | |
| 553 | { |
| 554 | std::lock_guard<std::recursive_mutex> lock(mMutex); |
| 555 | |
| 556 | mAccessToken = std::string(tokenType) + " " + accessToken; |
| 557 | mTokenExpirationTime = |
| 558 | Clock::now() + std::chrono::seconds(expiresIn); |
| 559 | } |
| 560 | |
| 561 | BasicUI::CallAfter( |
| 562 | [token = std::string(newRefreshToken)]() |
| 563 | { |
| 564 | // At this point access token is already written, |
| 565 | // only refresh token is updated. |
| 566 | refreshToken.Write(token); |
| 567 | gPrefs->Flush(); |
| 568 | }); |
| 569 | |
| 570 | if (successCallback) |
| 571 | successCallback(mAccessToken); |
| 572 | |
| 573 | // The callback only needs the access token, so invoke it immediately. |
| 574 | // Networking is thread safe |
| 575 | SafePublish({ mAccessToken, {}, trace, true, silent }); |
| 576 | } |
| 577 | |
| 578 | void OAuthService::SafePublish(const AuthStateChangedMessage& message) |
| 579 | { |