forked from philosowaffle/peloton-to-garmin
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[410] support Garmin MFA login (philosowaffle#432)
* [410] support Garmin MFA login * refactor and cleaning up poc code * some cleanup * settings controller - add 2fa setting * webui - manage 2fa setting * webui - blocks sync if mfa enabled and no auth initialized yet * background sync - wont run when MFA enabled * garmin auth service stuff * webui - mfa flows are working * webui - polish * console - polish * docs updated * cleanup
- Loading branch information
1 parent
8b8160e
commit c4096ee
Showing
43 changed files
with
1,183 additions
and
433 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -234,6 +234,7 @@ This section provides settings related to uploading workouts to Garmin. | |
"Garmin": { | ||
"Email": "[email protected]", | ||
"Password": "garmin", | ||
"TwoStepVerificationEnabled": false, | ||
"Upload": false, | ||
"FormatToUpload": "fit", | ||
"UploadStrategy": 2 | ||
|
@@ -250,6 +251,7 @@ This section provides settings related to uploading workouts to Garmin. | |
|:-----------|:---------|:--------|:--------------------|:------------| | ||
| Email | **yes - if Upload=true** | `null` | `Garmin Tab` | Your Garmin email used to sign in | | ||
| Password | **yes - if Upload=true** | `null` | `Garmin Tab` | Your Garmin password used to sign in | | ||
| TwoStepVerificationEnabled | no | `false` | `Garmin Tab` | Whether or not your Garmin account is protected by Two Step Verification | | ||
| Upload | no | `false` | `Garmin Tab` | `true` indicates you wish downloaded workouts to be automatically uploaded to Garmin for you. | | ||
| FormatToUpload | no | `fit` | `Garmin Tab > Advanced` | Valid values are `fit` or `tcx`. Ensure the format you specify here is also enabled in your [Format config](#format-config) | | ||
| UploadStrategy | **yes if Upload=true** | `null` | `Garmin Tab > Advanced` | Allows configuring different upload strategies for syncing with Garmin. Valid values are `[0 - PythonAndGuploadInstalledLocally, 1 - WindowsExeBundledPython, 2 - NativeImplV1]`. See [upload strategies](#upload-strategies) for more info. | | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
using Common.Dto.Api; | ||
using Common.Helpers; | ||
using Common.Service; | ||
using Garmin.Auth; | ||
using Microsoft.AspNetCore.Mvc; | ||
|
||
namespace Api.Controllers | ||
{ | ||
[ApiController] | ||
[Produces("application/json")] | ||
[Consumes("application/json")] | ||
public class GarminAuthenticationController : Controller | ||
{ | ||
private readonly IGarminAuthenticationService _garminAuthService; | ||
private readonly ISettingsService _settingsService; | ||
|
||
public GarminAuthenticationController(IGarminAuthenticationService garminAuthService, ISettingsService settingsService) | ||
{ | ||
_garminAuthService = garminAuthService; | ||
_settingsService = settingsService; | ||
} | ||
|
||
[HttpGet] | ||
[Route("api/garminauthentication")] | ||
[ProducesResponseType(StatusCodes.Status200OK)] | ||
public async Task<ActionResult<GarminAuthenticationGetResponse>> GetAsync() | ||
{ | ||
var settings = await _settingsService.GetSettingsAsync(); | ||
var auth = _settingsService.GetGarminAuthentication(settings.Garmin.Email); | ||
|
||
var result = new GarminAuthenticationGetResponse() { IsAuthenticated = auth?.IsValid(settings) ?? false }; | ||
return Ok(result); | ||
} | ||
|
||
/// <summary> | ||
/// Initializes Garmin authentication. When TwoStep verification is enabled, will perform part one of the auth | ||
/// flow, triggering and Email or Text to the user with an MFA code. This flow will be completed by calling | ||
/// POST api/garminauthentication/mfaToken | ||
/// </summary> | ||
/// <returns>201 - Garmin Authentication was successfully initialized.</returns> | ||
/// <returns>202 - Garmin Authentication was successfully started but needs MFA token to be completed.</returns> | ||
[HttpPost] | ||
[Route("api/garminauthentication/signin")] | ||
[ProducesResponseType(StatusCodes.Status201Created)] | ||
[ProducesResponseType(StatusCodes.Status202Accepted)] | ||
public async Task<ActionResult> SignInAsync() | ||
{ | ||
var settings = await _settingsService.GetSettingsAsync(); | ||
|
||
if (settings.Garmin.Password.CheckIsNullOrEmpty("Garmin Password", out var result)) return result; | ||
if (settings.Garmin.Email.CheckIsNullOrEmpty("Garmin Email", out result)) return result; | ||
|
||
try | ||
{ | ||
if (!settings.Garmin.TwoStepVerificationEnabled) | ||
{ | ||
await _garminAuthService.RefreshGarminAuthenticationAsync(); | ||
return Created("api/garminauthentication", new GarminAuthenticationGetResponse() { IsAuthenticated = true }); | ||
} | ||
else | ||
{ | ||
var auth = await _garminAuthService.RefreshGarminAuthenticationAsync(); | ||
|
||
if (auth.AuthStage == Common.Stateful.AuthStage.NeedMfaToken) | ||
return Accepted(); | ||
|
||
return Created("api/garminauthentication", new GarminAuthenticationGetResponse() { IsAuthenticated = true }); | ||
} | ||
} | ||
catch (GarminAuthenticationError gae) when (gae.Code == Code.UnexpectedMfa) | ||
{ | ||
return BadRequest(new ErrorResponse("It looks like your account is protected by two step verification. Please enable the Two Step verification setting.")); | ||
} | ||
catch (GarminAuthenticationError gae) when (gae.Code == Code.InvalidCredentials) | ||
{ | ||
return Unauthorized(new ErrorResponse("Garmin authentication failed. Invalid Garmin credentials.")); | ||
} | ||
catch (Exception e) | ||
{ | ||
return StatusCode(StatusCodes.Status500InternalServerError, new ErrorResponse($"Unexpected error occurred: {e.Message}")); | ||
} | ||
} | ||
|
||
[HttpPost] | ||
[Route("api/garminauthentication/mfaToken")] | ||
[ProducesResponseType(StatusCodes.Status201Created)] | ||
public async Task<ActionResult> PostMfaTokenAsync([FromBody] GarminAuthenticationMfaTokenPostRequest request) | ||
{ | ||
var settings = await _settingsService.GetSettingsAsync(); | ||
|
||
if (!settings.Garmin.TwoStepVerificationEnabled) | ||
return BadRequest(new ErrorResponse("Garmin two step verification is not enabled in Settings.")); | ||
|
||
try | ||
{ | ||
await _garminAuthService.CompleteMFAAuthAsync(request.MfaToken); | ||
return Created("api/garminauthentication", new GarminAuthenticationGetResponse() { IsAuthenticated = true }); | ||
} | ||
catch (Exception e) | ||
{ | ||
return StatusCode(StatusCodes.Status500InternalServerError, new ErrorResponse($"Unexpected error occurred: {e.Message}")); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.