Skip to content

Commit

Permalink
Merge pull request #61 from Tune-Fun/fix/account/apple_social_unlink_…
Browse files Browse the repository at this point in the history
…client_secret

fix(oauth2) Revoke
  • Loading branch information
habinkim authored Apr 10, 2024
2 parents 421bc98 + aa648c2 commit c99f132
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.tune_fun.v1.account.application.service.oauth2.decorator;

import com.tune_fun.v1.common.helper.AppleOAuth2ClientSecretHelper;
import com.tune_fun.v1.common.property.AppleProperty;
import com.tune_fun.v1.common.util.EncryptUtil;
import io.jsonwebtoken.Jwts;
Expand Down Expand Up @@ -27,8 +28,7 @@
@RequiredArgsConstructor
public class OAuth2AuthorizationCodeGrantRequestEntityDecorator extends OAuth2AuthorizationCodeGrantRequestEntityConverter {

private final AppleProperty appleProperty;
private final OAuth2ClientProperties oAuth2ClientProperties;
private final AppleOAuth2ClientSecretHelper appleOAuth2ClientSecretHelper;


@Override
Expand All @@ -51,7 +51,7 @@ public RequestEntity<?> convert(@NotNull OAuth2AuthorizationCodeGrantRequest req

String clientSecret;
try {
clientSecret = createAppleClientSecret();
clientSecret = appleOAuth2ClientSecretHelper.createAppleClientSecret();
} catch (IOException e) {
throw new IllegalStateException("Error while creating Apple client secret.");
}
Expand All @@ -61,23 +61,4 @@ public RequestEntity<?> convert(@NotNull OAuth2AuthorizationCodeGrantRequest req
return new RequestEntity<>(params, entity.getHeaders(), entity.getMethod(), entity.getUrl());
}

private String createAppleClientSecret() throws IOException {
Instant expirationInstant = Instant.now().plusSeconds(30 * 24 * 60 * 60); // 30 days in seconds
final StringReader appleOAuth2KeyReader = new StringReader(appleProperty.oauth2Key());
final PrivateKey appleOAuth2PrivateKey = EncryptUtil.parsePemAndGetPrivateKey(appleOAuth2KeyReader);


return Jwts.builder()
.header().add("kid", appleProperty.keyId())
.and()
.issuer(appleProperty.teamId())
.issuedAt(Date.from(Instant.now()))
.expiration(Date.from(expirationInstant))
.audience().add("https://appleid.apple.com")
.and()
.subject(oAuth2ClientProperties.getRegistration().get(APPLE.getRegistrationId()).getClientId())
.signWith(appleOAuth2PrivateKey, Jwts.SIG.ES256)
.compact();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
import com.tune_fun.v1.account.domain.state.oauth2.*;
import com.tune_fun.v1.common.exception.CommonApplicationException;
import com.tune_fun.v1.common.exception.OAuth2AuthenticationProcessingException;
import com.tune_fun.v1.common.helper.AppleOAuth2ClientSecretHelper;
import com.tune_fun.v1.common.hexagon.UseCase;
import com.tune_fun.v1.common.util.StringUtil;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties;
Expand Down Expand Up @@ -67,6 +69,8 @@ public class OAuth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS
private final RevokeOAuth2GooglePort revokeOAuth2GooglePort;
private final RevokeOAuth2ApplePort revokeOAuth2ApplePort;

private final AppleOAuth2ClientSecretHelper appleOAuth2ClientSecretHelper;

private static final Function<String, String> AUTH_FAILED_URL_FUNCTION = targetUrl ->
fromUriString(targetUrl).queryParam("error", "Authorization failed")
.build().toUriString();
Expand All @@ -86,6 +90,7 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo
getRedirectStrategy().sendRedirect(request, response, targetUrl);
}

@SneakyThrows
@Transactional
public String determineTargetUrl(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) {
Expand Down Expand Up @@ -147,7 +152,7 @@ private String createJwtTokenAndRedirectUri(final OAuth2UserPrincipal principal,
}

@Transactional
public String unlink(final OAuth2UserPrincipal principal, final String targetUrl, HttpServletRequest request) {
public String unlink(final OAuth2UserPrincipal principal, final String targetUrl, HttpServletRequest request) throws IOException {
Optional<String> usernameOptional = getCookie(request, USERNAME_PARAM_COOKIE_NAME).map(Cookie::getValue);
if (usernameOptional.isEmpty()) return AUTH_FAILED_URL_FUNCTION.apply(targetUrl);

Expand Down Expand Up @@ -208,7 +213,7 @@ public void saveOAuth2Account(final OAuth2UserPrincipal principal, final Account
saveOAuth2AccountPort.saveOAuth2Account(saveOAuth2AccountBehavior);
}

private void unlinkHttpRequest(final OAuth2Provider provider, final String accessToken) {
private void unlinkHttpRequest(final OAuth2Provider provider, final String accessToken) throws IOException {
if (accessToken == null || accessToken.trim().isEmpty())
throw new OAuth2AuthenticationProcessingException("Access token must not be null or empty");

Expand All @@ -224,14 +229,14 @@ private void unlinkHttpRequest(final OAuth2Provider provider, final String acces
}

@NotNull
private RevokeOAuth2AppleRequest getRevokeOAuth2AppleRequest(final String accessToken) {
private RevokeOAuth2AppleRequest getRevokeOAuth2AppleRequest(final String accessToken) throws IOException {
OAuth2ClientProperties.Registration registration = oAuth2ClientProperties
.getRegistration()
.get(APPLE.getRegistrationId());

if (registration == null) throw new OAuth2AuthenticationProcessingException("Apple registration not found");

return new RevokeOAuth2AppleRequest(registration.getClientId(), registration.getClientSecret(), accessToken);
return new RevokeOAuth2AppleRequest(registration.getClientId(), appleOAuth2ClientSecretHelper.createAppleClientSecret(), accessToken);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.tune_fun.v1.common.helper;

import com.tune_fun.v1.common.property.AppleProperty;
import com.tune_fun.v1.common.util.EncryptUtil;
import io.jsonwebtoken.Jwts;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.StringReader;
import java.security.PrivateKey;
import java.time.Instant;
import java.util.Date;

import static com.tune_fun.v1.account.domain.state.oauth2.OAuth2Provider.APPLE;

@Component
@RequiredArgsConstructor
public class AppleOAuth2ClientSecretHelper {

private final AppleProperty appleProperty;
private final OAuth2ClientProperties oAuth2ClientProperties;

public String createAppleClientSecret() throws IOException {
Instant expirationInstant = Instant.now().plusSeconds(30 * 24 * 60 * 60); // 30 days in seconds
final StringReader appleOAuth2KeyReader = new StringReader(appleProperty.oauth2Key());
final PrivateKey appleOAuth2PrivateKey = EncryptUtil.parsePemAndGetPrivateKey(appleOAuth2KeyReader);


return Jwts.builder()
.header().add("kid", appleProperty.keyId())
.and()
.issuer(appleProperty.teamId())
.issuedAt(Date.from(Instant.now()))
.expiration(Date.from(expirationInstant))
.audience().add("https://appleid.apple.com")
.and()
.subject(oAuth2ClientProperties.getRegistration().get(APPLE.getRegistrationId()).getClientId())
.signWith(appleOAuth2PrivateKey, Jwts.SIG.ES256)
.compact();
}

}

0 comments on commit c99f132

Please sign in to comment.