コード例 #1
0
 public StravaConnectController(
     IOptions <SegmentChallengeConfiguration> challengeConfiguration,
     IOptions <StravaConfiguration> stravaConfiguration,
     Func <DbConnection> dbConnectionFactory,
     StravaApiHelper apiHelper,
     ILogger <StravaConnectController> logger)
 {
     this.challengeConfiguration = challengeConfiguration;
     this.stravaConfiguration    = stravaConfiguration;
     this.dbConnectionFactory    = dbConnectionFactory;
     this.apiHelper = apiHelper;
     this.logger    = logger;
 }
コード例 #2
0
        public async Task <IActionResult> Authorize(
            [FromQuery] String state,
            [FromQuery] String code,
            [FromQuery] String scope,
            CancellationToken cancellationToken)
        {
            var expected_state = Request.Cookies["authentication_state"];

            if (!String.Equals(state, expected_state))
            {
                this.logger.LogWarning(
                    "The state {ActualState} did not match the expected authentication state {ExpectedState}",
                    state,
                    expected_state
                    );
            }

            var codeExchangeClient =
                new HttpClient {
                BaseAddress = new Uri("https://www.strava.com")
            };

            codeExchangeClient.DefaultRequestHeaders.Add("Accept", "application/json");

            var response =
                await this.apiHelper.MakeThrottledApiRequest(
                    () => codeExchangeClient.PostAsync(
                        "/api/v3/oauth/token",
                        new FormUrlEncodedContent(new Dictionary <string, string> {
                { "client_id", this.stravaConfiguration.Value.ClientId },
                { "client_secret", this.stravaConfiguration.Value.ClientSecret },
                { "code", code },
                { "grant_type", "authorization_code" }
            }),
                        cancellationToken
                        ),
                    cancellationToken);

            if (response.IsSuccessStatusCode)
            {
                var session =
                    await response.Content.ReadAsAsync <StravaSession>(cancellationToken);

                await using var connection = this.dbConnectionFactory();
                await connection.OpenAsync(cancellationToken);

                await using var dbContext = new SegmentChallengeDbContext(connection);

                var athleteTable = dbContext.Set <Athlete>();
                // Does user exist? If not create them.
                var existingAthlete =
                    await athleteTable.SingleOrDefaultAsync(a => a.Id == session.Athlete.Id,
                                                            cancellationToken);

                EntityEntry <Athlete> newAthlete = null;
                if (existingAthlete == null)
                {
                    newAthlete = await athleteTable.AddAsync(
                        new Athlete {
                        Id        = session.Athlete.Id,
                        Username  = session.Athlete.Username,
                        FirstName = session.Athlete.FirstName,
                        LastName  = session.Athlete.LastName,
                        Gender    = !String.IsNullOrEmpty(session.Athlete.Sex) ?
                                    session.Athlete.Sex[0] :
                                    (Char?)null,
                        ProfilePicture =
                            session.Athlete.ProfileMedium ?? session.Athlete.Profile,
                        AccessToken     = session.AccessToken,
                        RefreshToken    = session.RefreshToken,
                        TokenExpiration =
                            StravaApiHelper.DateTimeFromUnixTime(session.ExpiresAt)
                    },
                        cancellationToken
                        );
                }
                else
                {
                    existingAthlete.Username  = session.Athlete.Username;
                    existingAthlete.FirstName = session.Athlete.FirstName;
                    existingAthlete.LastName  = session.Athlete.LastName;
                    if (!String.IsNullOrEmpty(session.Athlete.Sex))
                    {
                        existingAthlete.Gender = session.Athlete.Sex[0];
                    }

                    existingAthlete.ProfilePicture =
                        session.Athlete.ProfileMedium ?? session.Athlete.Profile;
                    existingAthlete.AccessToken     = session.AccessToken;
                    existingAthlete.RefreshToken    = session.RefreshToken;
                    existingAthlete.TokenExpiration =
                        StravaApiHelper.DateTimeFromUnixTime(session.ExpiresAt);

                    athleteTable.Update(existingAthlete);
                }

                var changes = await dbContext.SaveChangesAsync(cancellationToken);

                if (changes != 1)
                {
                    logger.LogWarning(
                        $"Unexpected number of rows changed {(existingAthlete == null ? "creating" : "updating")} Athlete {{AthleteId}} ({{RowsChanged}})",
                        session.Athlete.Id,
                        changes
                        );
                }

                Response.Cookies.Append(
                    "id_token",
                    CreateAthleteJwt(
                        this.challengeConfiguration.Value,
                        existingAthlete ?? newAthlete?.Entity),
                    new CookieOptions {
                    Expires = DateTime.UtcNow.AddDays(this.challengeConfiguration.Value.TokenExpiration)
                }
                    );


                return(Redirect("/"));
            }
            else
            {
                logger.LogError(
                    "Authentication Failed with HTTP Status {StatusCode}: {Content}",
                    response.StatusCode,
                    await response.Content.ReadAsStringAsync()
                    );

                return(this.Problem(
                           $"An unexpected error occurred. Please contact {this.challengeConfiguration.Value.SupportContact}"));
            }
        }