Skip to content

Commit

Permalink
🐛 Fix: Improve Google OAuth login flow.
Browse files Browse the repository at this point in the history
  • Loading branch information
hanbings committed Jul 17, 2023
1 parent b0a20ac commit c20dc4b
Show file tree
Hide file tree
Showing 5 changed files with 247 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.SerializedName;
import io.hanbings.flows.common.interfaces.Access;
import io.hanbings.flows.common.interfaces.Refresh;

public record GoogleAccess(
@JsonProperty("access_token")
Expand All @@ -36,14 +37,14 @@ public record GoogleAccess(
@JsonProperty("token_type")
@SerializedName("token_type")
String tokenType
) implements Access {
) implements Access, Refresh {
public record Wrong(
@JsonProperty("error")
@SerializedName("error")
String error,
@JsonProperty("error_description")
@SerializedName("error_description")
String errorDescription
) implements Access.Wrong {
) implements Access.Wrong, Refresh.Wrong {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.hanbings.flows.google;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.SerializedName;
import io.hanbings.flows.common.interfaces.Identify;

public record GoogleIdentify(
@JsonProperty("sub")
@SerializedName("sub")
String openid,
@JsonProperty("picture")
@SerializedName("picture")
String avatar,
@JsonProperty("name")
@SerializedName("name")
String username,
@JsonProperty("username")
@SerializedName("username")
String nickname,
@JsonProperty("email")
@SerializedName("email")
String email,
String phone
) implements Identify {
public record Wrong(
@JsonProperty("error")
@SerializedName("error")
String error,
@JsonProperty("error_description")
@SerializedName("error_description")
String errorDescription
) implements Identify.Wrong {
}
}
157 changes: 154 additions & 3 deletions flows-google/src/main/java/io/hanbings/flows/google/GoogleOAuth.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,25 @@

import io.hanbings.flows.common.OAuth;
import io.hanbings.flows.common.OAuthCallback;
import io.hanbings.flows.common.interfaces.Callback;
import io.hanbings.flows.common.interfaces.Response;
import io.hanbings.flows.common.interfaces.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SuppressWarnings("unused")
public class GoogleOAuth extends OAuth<GoogleAccess, GoogleAccess.Wrong> {
public class GoogleOAuth
extends
OAuth<GoogleAccess, GoogleAccess.Wrong>
implements
Profilable<GoogleProfile, GoogleProfile.Wrong>,
Identifiable<GoogleIdentify, GoogleIdentify.Wrong>,
Revokable<GoogleRevoke, GoogleRevoke.Wrong>,
Refreshable<GoogleAccess, GoogleAccess.Wrong> {
final String USER_INFO = "https://openidconnect.googleapis.com/v1/userinfo";
final String refreshment = "https://oauth2.googleapis.com/token";
final String revocation = "https://oauth2.googleapis.com/revoke";

private GoogleOAuth() {
super(null, null, null, null);
}
Expand Down Expand Up @@ -112,4 +122,145 @@ public Callback<GoogleAccess, GoogleAccess.Wrong> token(String code, String stat
response.exception() ? response.throwable() : new IllegalArgumentException()
);
}

@Override
public Callback<GoogleIdentify, GoogleIdentify.Wrong> identify(String token) {
Response response = this.request()
.get()
.get(
this.serialization().get(),
this.proxy() == null ? null : this.proxy().get(),
USER_INFO,
Map.of("access_token", token)
);

if (response.code() == 200) {
GoogleIdentify identify = this.serialization()
.get()
.object(GoogleIdentify.class, response.raw());

return OAuthCallback.response(token, identify, null, response);
}

if (response.code() != 200 && response.code() != 0) {
GoogleIdentify.Wrong wrong = this.serialization()
.get()
.object(GoogleIdentify.Wrong.class, response.raw());

return OAuthCallback.response(null, null, wrong, response);
}

return OAuthCallback.exception(
null,
response.exception() ? response.throwable() : new IllegalArgumentException()
);
}

@Override
public Callback<GoogleProfile, GoogleProfile.Wrong> profile(String token) {
Response response = this.request()
.get()
.get(
this.serialization().get(),
this.proxy() == null ? null : this.proxy().get(),
USER_INFO,
Map.of("access_token", token)
);

if (response.code() == 200) {
GoogleProfile profile = this.serialization()
.get()
.object(GoogleProfile.class, response.raw());

return OAuthCallback.response(token, profile, null, response);
}

if (response.code() != 200 && response.code() != 0) {
GoogleProfile.Wrong wrong = this.serialization()
.get()
.object(GoogleProfile.Wrong.class, response.raw());

return OAuthCallback.response(null, null, wrong, response);
}

return OAuthCallback.exception(
null,
response.exception() ? response.throwable() : new IllegalArgumentException()
);
}

@Override
public Callback<GoogleAccess, GoogleAccess.Wrong> refresh(String token) {
Response response = this.request()
.get()
.post(
this.serialization().get(),
this.proxy() == null ? null : this.proxy().get(),
refreshment,
Map.of(
"client_id", this.client(),
"client_secret", this.secret(),
"grant_type", "refresh_token",
"refresh_token", token
),
Map.of(
"Accept", "application/json",
"Content-Type", "application/x-www-form-urlencoded"
)
);

if (response.code() == 200) {
GoogleAccess access = this.serialization()
.get()
.object(GoogleAccess.class, response.raw());

return OAuthCallback.response(access.accessToken(), access, null, response);
}

if (response.code() != 200 && response.code() != 0) {
GoogleAccess.Wrong wrong = this.serialization()
.get()
.object(GoogleAccess.Wrong.class, response.raw());

return OAuthCallback.response(null, null, wrong, response);
}

return OAuthCallback.exception(
null,
response.exception() ? response.throwable() : new IllegalArgumentException()
);
}

@Override
public Callback<GoogleRevoke, GoogleRevoke.Wrong> revoke(String token) {
Response response = this.request()
.get()
.get(
this.serialization().get(),
this.proxy() == null ? null : this.proxy().get(),
revocation,
Map.of("token", token)
);

if (response.code() == 200) {
GoogleRevoke revoke = this.serialization()
.get()
.object(GoogleRevoke.class, response.raw());

return OAuthCallback.response(token, revoke, null, response);
}

if (response.code() != 200 && response.code() != 0) {
GoogleRevoke.Wrong wrong = this.serialization()
.get()
.object(GoogleRevoke.Wrong.class, response.raw());

return OAuthCallback.response(null, null, wrong, response);
}

return OAuthCallback.exception(
null,
response.exception() ? response.throwable() : new IllegalArgumentException()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package io.hanbings.flows.google;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.SerializedName;
import io.hanbings.flows.common.interfaces.Profile;

public record GoogleProfile(
@JsonProperty("sub")
@SerializedName("sub")
String sub,
@JsonProperty("name")
@SerializedName("name")
String name,
@JsonProperty("given_name")
@SerializedName("given_name")
String givenName,
@JsonProperty("family_name")
@SerializedName("family_name")
String familyName,
@JsonProperty("picture")
@SerializedName("picture")
String picture,
@JsonProperty("email")
@SerializedName("email")
String email,
@JsonProperty("locale")
@SerializedName("locale")
String locale
) implements Profile {
public record Wrong(
@JsonProperty("error")
@SerializedName("error")
String error,
@JsonProperty("error_description")
@SerializedName("error_description")
String errorDescription
) implements Profile.Wrong {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.hanbings.flows.google;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.SerializedName;
import io.hanbings.flows.common.interfaces.Revoke;

public record GoogleRevoke() implements Revoke {
public record Wrong(
@JsonProperty("error")
@SerializedName("error")
String error,
@JsonProperty("error_description")
@SerializedName("error_description")
String errorDescription
) implements Revoke.Wrong {
}
}

0 comments on commit c20dc4b

Please sign in to comment.