Java oauth2 проблема с внедрением внешнего апи

Рейтинг: 1Ответов: 0Опубликовано: 07.04.2023

Вот примерная логика приложения:

  1. Пользователь заходит в приложение через обычную форму Логин+Пароль
  2. Юзер хочет открыть информацию о его спортивных действиях и заходит в нужную вкладку
  3. Клиент (флаттер) отправляет его запрос на бэк (джава)
  4. На бэке с учётом client id и прочего генерируется нужная ссылка и возвращается на фронт
  5. Фронт перенаправляет пользователя на страницу авторизации
  6. После авторизации приходит запрос на callback url, где приходит код
  7. С этим кодом бэк через rest template получает токен
  8. Сохраняю токен в базе данных
  9. Через диплинк возвращаю пользователя в мобильное приложение

Проблема возникает на 8 шаге, так как на этот эндпоинт приходит запрос с внешнего апи, я не могу никак определить, к какому пользователю мне прикрепить данный токен (пользователь уже залогинен в приложении и авторизация через классическое Oauth2 не подходит).

Вот код контроллера и сервиса:

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/strava")
public class StravaController {
private final StravaService stravaService;

@GetMapping("/token/location")
public String getLocation(HttpServletResponse response) throws IOException {
    return stravaService.getLocation();
}

@GetMapping("/token/callback")
public String getToken(@RequestParam String code) throws URISyntaxException {
    String location = stravaService.getToken(code);
    return "<html>\n" + "<header><title>Welcome</title></header>\n" +
            "<body>\n" + "<a href=\"" + location + "\">Click</a>" + "</body>\n" + "</html>";
}
}

Проблема возникает, когда я пытаюсь получить текущего пользователя из SecurityContextHolder:

@Slf4j
@Service
@RequiredArgsConstructor
public class StravaService {
private final StravaTokenRepository stravaTokenRepository;
private final AccountService accountService;

@Value("${strava.client_id}")
private String client_id;
@Value("${strava.client_secret}")
private String client_secret;
@Value("${strava.redirect_uri}")
private String redirect_uri;
@Value("${strava.response_type}")
private String response_type;
@Value("${strava.scope}")
private String scope;
@Value("${strava.grant_type}")
private String grant_type;
@Value("${mobile_app.redirect_uri}")
private String mobileRedirectUri;

private static final String AUTHORIZATION_ENDPOINT = "https://www.strava.com/oauth/authorize";
private static final String TOKEN_ENDPOINT = "https://www.strava.com/oauth/token";

public String getLocation() throws IOException {
    Map<String, String> queryParameters = new HashMap<>();
    queryParameters.put("client_id", client_id);
    queryParameters.put("response_type", response_type);
    queryParameters.put("redirect_uri", redirect_uri);
    queryParameters.put("scope", scope);

    return buildUrl(AUTHORIZATION_ENDPOINT, queryParameters);
}

public String getToken(String code) throws URISyntaxException {
    Account account = accountService.getCurrentUser();

    MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();

    parameters.add("code", code);
    parameters.add("client_id", client_id);
    parameters.add("client_secret", client_secret);
    parameters.add("grant_type", grant_type);

    RestTemplate restTemplate = new RestTemplate();

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

    HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(parameters, headers);

    URI uri = new URI(TOKEN_ENDPOINT);

    ResponseEntity<StravaTokenDetails> response = restTemplate.exchange(uri, HttpMethod.POST, request, StravaTokenDetails.class);

    StravaTokenDetails stravaTokenDetails = response.getBody();
    stravaTokenRepository.save(StravaToken.builder()
            .accessToken(stravaTokenDetails.getAccessToken())
            .refreshToken(stravaTokenDetails.getRefreshToken())
            .expiresAt(stravaTokenDetails.getExpiresAt())
            .account(account)
            .build());

    return mobileRedirectUri;
}

// Helper method to build a URL with query parameters
private String buildUrl (String endpoint, Map < String, String > queryParameters) throws IOException {
    StringBuilder queryBuilder = new StringBuilder();
    for (Map.Entry<String, String> entry : queryParameters.entrySet()) {
        if (queryBuilder.length() > 0) {
            queryBuilder.append("&");
        }
        queryBuilder.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
        queryBuilder.append("=");
        queryBuilder.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
    }
    return endpoint + "?" + queryBuilder.toString();
}
}
    @Transactional(readOnly = true)
    public Account getCurrentUser() {
        String username = SecurityContextHolder.getContext().getAuthentication().getName();
        return accountRepository.findAccountByEmailIgnoreCase(username).orElseThrow(EntityNotFoundException::new);
    }

Ответы

Ответов пока нет.