diff --git a/README.md b/README.md index f4fafcd..9c4b532 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Next, you have to configure your web page for Sign in with Apple. Follow the gui # Example ## Using `AppleAuthProvider.java` `AppleClientPrivateKeyFactory.java` First order of business should be creating an instance of `ECPrivateKey` representing the client's(your) private key.
-`AppleKeyProvider` can help you create a `ECPrivateKey` if you have your private key as string or stream (from a p8 for example). +`AppleClientPrivateKeyFactory` can help you create a `ECPrivateKey` if you have your private key as string or stream (from a p8 for example). Creating a new instance of `AppleAuthProvider`, should be trivial at this point. The only two parameters that are not self explanatory are the `SecretGenerator` and the collection of scopes.
@@ -30,10 +30,10 @@ Once you have your `AppleAuthProvider` instance you can: ## Handling initial response from Apple After the user clicks on the "Sign in with Apple" button on your page they will be redirected to https://appleid.apple.com/. After they provide their credentials Apple will make a POST request to the url that you have specified as Redirect URL. -It will contain a ```code``` field. Its contents is what should be handed down to `makeNewAuthorisationTokenRequest` in order retrieve thee authorization token (it will also contain the state used to create the redirect url). +It will contain a `code` field. Its contents is what should be handed down to `makeNewAuthorisationTokenRequest` in order retrieve the authorization token (it will also contain the state used to create the redirect url). Keep in mind that tokens returned from Apple are short-lived, so you should create a session or a user in your system -using the returned ```AppleAuthorizationToken``` object. After that you can verify if the user is -still logged in using "Sign in with Apple" by retrieving a refresh token using the ```makeNewRefreshTokenRequest``` method. +using the returned `AppleAuthorizationToken` object. After that you can verify if the user is +still logged in using "Sign in with Apple" by retrieving a refresh token using the `makeNewRefreshTokenRequest` method. ```java public class AppleIdTokenManager { @@ -44,14 +44,14 @@ still logged in using "Sign in with Apple" by retrieving a refresh token using t private static final String REDIRECT_URL = "Your redirect url"; public static void main(String[] args) throws IOException, InvalidKeySpecException { - //Generating your private key. - //This could be just a string containing the key. + // Generating your private key. + // This could be just a string containing the key. InputStream pkStream = AppleIdTokenManager.class .getClassLoader().getResourceAsStream("your_pk_file.p8"); AppleClientPrivateKeyFactory appleClientPrivateKeyFactory = new AppleClientPrivateKeyFactory(); ECPrivateKey privateKey = appleClientPrivateKeyFactory.getEcPrivateKey(pkStream); - //Creating provider instance. + // Creating provider instance. SecretGenerator secretGenerator = new SecretGenerator(); AppleAuthProvider appleAuthProvider = new AppleAuthProvider( CLIENT_ID, @@ -63,20 +63,20 @@ still logged in using "Sign in with Apple" by retrieving a refresh token using t REDIRECT_URL ); - //We are ready to start using the provider. + // We are ready to start using the provider. - //Generate a url and navigate the user to it. + // Generate a url and navigate the user to it. String loginLink = appleAuthProvider.getLoginLink("Some form of state"); - //Once the user is redirected back to our domain get the "code" in the request. + // Once the user is redirected back to our domain get the "code" in the request. String authCode = "the code in the callback request"; - //Now we can authenticate the user. + // Now we can authenticate the user. AppleAuthorizationToken initialToken = appleAuthProvider.makeNewAuthorisationTokenRequest(authCode); - //After the authentication we should check (not more than once every once 24 hours) if the user still - // logged in using "Sign in with Apple" by retrieving a refresh token. + // After the authentication we should check (not more than once every 24h) if the user + // is still logged in using "Sign in with Apple" by retrieving a refresh token. AppleAuthorizationToken refreshToken = appleAuthProvider.makeNewRefreshTokenRequest(initialToken .getRefreshToken()); } } -``` \ No newline at end of file +``` diff --git a/pom.xml b/pom.xml index 9e4a786..a31aa6d 100644 --- a/pom.xml +++ b/pom.xml @@ -84,21 +84,20 @@ com.auth0 java-jwt - 3.10.3 + 4.0.0 com.auth0 jwks-rsa - 0.11.0 + 0.21.1 com.google.api-client google-api-client - 1.30.9 + 2.0.0 - - \ No newline at end of file + diff --git a/src/main/java/com/accedia/apple/auth/AppleAuthProvider.java b/src/main/java/com/accedia/apple/auth/AppleAuthProvider.java index a8a4f2a..fd904c6 100644 --- a/src/main/java/com/accedia/apple/auth/AppleAuthProvider.java +++ b/src/main/java/com/accedia/apple/auth/AppleAuthProvider.java @@ -12,7 +12,7 @@ import com.google.api.client.http.HttpTransport; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.JsonFactory; -import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.client.json.gson.GsonFactory; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; @@ -26,7 +26,8 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; + +import static java.util.stream.Collectors.toList; public class AppleAuthProvider { @@ -45,7 +46,7 @@ public class AppleAuthProvider { private final long secretLifeInSec; private final GenericUrl appleAuthTokenUrl; private final String appleAuthAuthorizationUrl; - private UserDataDeserializer userDataDeserializer; + private final UserDataDeserializer userDataDeserializer; private final List appleUserScopes; private final String redirectUrl; private final HttpTransport httpTransport; @@ -81,11 +82,11 @@ public AppleAuthProvider(String clientId, String keyId, String teamId, SecretGen DEFAULT_APPLE_AUTH_AUTHORIZE_URL, new UserDataDeserializer(), new NetHttpTransport(), - new JacksonFactory(), + new GsonFactory(), DEFAULT_MAX_TIMEOUT_IN_SEC, secretGenerator, privateKey, - () -> Instant.now(), + Instant::now, DEFAULT_SECRET_LIFE_IN_SEC, new AppleKeyProvider(), scopes, @@ -146,7 +147,7 @@ public AppleAuthProvider(String clientId, this.secretLifeInSec = secretLifeInSec; this.userDataDeserializer = userDataDeserializer; this.appleUserScopes = scopes != null ? ImmutableList.copyOf( - scopes.stream().map(AppleUserScope::getLiteral).collect(Collectors.toList()) + scopes.stream().map(AppleUserScope::getLiteral).collect(toList()) ) : null; this.appleAuthTokenUrl = new GenericUrl(appleAuthTokenUrl); this.jsonFactory = jsonFactory; @@ -159,7 +160,7 @@ public AppleAuthProvider(String clientId, this.httpTransport = httpTransport; Algorithm validationAlg = Algorithm.RSA256(appleKeyProvider); - this.jwtVerifier = JWT.require(validationAlg) + this.jwtVerifier = JWT.require(validationAlg) .build(); } @@ -182,13 +183,13 @@ public String getLoginLink(String state) { .setResponseTypes(Arrays.asList("code", "id_token")) .setScopes(appleUserScopes) .setState(state) - .set("response_mode", "form_post")//Could be parameterized based on scope. + .set("response_mode", "form_post") //Could be parameterized based on scope. .build(); } /** - * Makes an authorisation request. Retrieves an User's date from Apple. Use this object to create users or sessions. - * @param authCode Received from Apple after successfully redirecting the use. + * Makes an authorisation request. Retrieves a User's date from Apple. Use this object to create users or sessions. + * @param authCode Received from Apple after successfully redirecting the user. * @throws IOException */ public AppleAuthorizationToken makeNewAuthorisationTokenRequest(String authCode) throws IOException { @@ -201,7 +202,7 @@ public AppleAuthorizationToken makeNewAuthorisationTokenRequest(String authCode) /** * Verifies if a token is valid. * Use this method to check daily if the user is still signed in on your app using Apple ID. - * @param refreshToken + * @param refreshToken * @return * @throws IOException */ @@ -218,13 +219,13 @@ private AppleAuthorizationToken executeTokenRequest(TokenRequest tokenRequest) t TokenResponse tokenResponse = tokenRequest.execute(); Optional idToken = Optional.ofNullable(tokenResponse.get("id_token")).map(Object::toString); idToken.ifPresent(this::validateToken); - Optional userData = idToken.map(userDataDeserializer::getUserDataFromIdToken); + UserData userData = idToken.map(userDataDeserializer::getUserDataFromIdToken).orElse(null); return new AppleAuthorizationToken( tokenResponse.getAccessToken(), tokenResponse.getExpiresInSeconds(), idToken.orElse(null), tokenResponse.getRefreshToken(), - userData.orElse(null)); + userData); } private void validateToken(String token) {