Fakultas Ilmu Komputer UI
Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
B
be-authentication-test
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Jira
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
SafetyPin
be-authentication-test
Commits
15e4e4b5
Commit
15e4e4b5
authored
2 months ago
by
Muhammad Raihan Akbar
Browse files
Options
Downloads
Patches
Plain Diff
[REFACTOR] Refactored GoogleAuthService to use composition over inheritance
parent
7013bf62
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/main/java/com/safetypin/authentication/service/GoogleAuthService.java
+112
-96
112 additions, 96 deletions
...m/safetypin/authentication/service/GoogleAuthService.java
with
112 additions
and
96 deletions
src/main/java/com/safetypin/authentication/service/GoogleAuthService.java
+
112
−
96
View file @
15e4e4b5
...
...
@@ -6,55 +6,111 @@ import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import
com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier
;
import
com.google.api.client.http.javanet.NetHttpTransport
;
import
com.google.api.client.json.gson.GsonFactory
;
import
com.google.gson.JsonArray
;
import
com.google.gson.JsonElement
;
import
com.google.gson.JsonObject
;
import
java.io.InputStream
;
import
java.net.HttpURLConnection
;
import
java.net.URL
;
import
java.io.BufferedReader
;
import
java.io.InputStreamReader
;
import
java.io.IOException
;
import
com.google.gson.JsonArray
;
import
com.google.gson.JsonParser
;
import
java.time.LocalDate
;
import
java.time.Year
;
import
java.util.Collections
;
import
java.util.Optional
;
import
com.safetypin.authentication.dto.GoogleAuthDTO
;
import
com.safetypin.authentication.exception.ApiException
;
import
com.safetypin.authentication.exception.InvalidCredentialsException
;
import
com.safetypin.authentication.exception.UserAlreadyExistsException
;
import
com.safetypin.authentication.model.User
;
import
com.safetypin.authentication.repository.UserRepository
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.security.crypto.password.PasswordEncoder
;
import
org.springframework.stereotype.Service
;
import
java.io.*
;
import
java.net.*
;
import
java.security.GeneralSecurityException
;
import
java.time.LocalDate
;
import
java.time.Year
;
import
java.util.Collections
;
import
java.util.Optional
;
@Service
public
class
GoogleAuthService
extends
AuthenticationService
{
public
class
GoogleAuthService
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
GoogleAuthService
.
class
);
private
final
UserService
userService
;
private
final
JwtService
jwtService
;
@Value
(
"${google.client.id:default}"
)
private
String
googleClientId
;
@Value
(
"${google.client.secret:default}"
)
private
String
googleClientSecret
;
public
static
final
String
EMAIL_PROVIDER
=
"GMAIL"
;
private
static
final
String
EMAIL_PROVIDER
=
"GOOGLE"
;
private
static
final
String
PEOPLE_API_BASE_URL
=
"https://people.googleapis.com/v1/people/me"
;
public
GoogleAuthService
(
UserRepository
userRepository
,
PasswordEncoder
passwordEncoder
,
OTPService
otpService
)
{
super
(
userRepository
,
passwordEncoder
,
otpService
);
private
static
final
String
BIRTHDAY
=
"birthdays"
;
public
GoogleAuthService
(
UserService
userService
,
JwtService
jwtService
)
{
this
.
userService
=
userService
;
this
.
jwtService
=
jwtService
;
}
protected
GoogleIdTokenVerifier
createIdTokenVerifier
()
{
public
String
authenticate
(
GoogleAuthDTO
googleAuthDTO
)
throws
ApiException
{
try
{
GoogleIdToken
.
Payload
payload
=
verifyIdToken
(
googleAuthDTO
.
getIdToken
());
String
email
=
payload
.
getEmail
();
String
name
=
(
String
)
payload
.
get
(
"name"
);
Optional
<
User
>
existingUser
=
userService
.
findByEmail
(
email
);
if
(
existingUser
.
isPresent
())
{
User
user
=
existingUser
.
get
();
String
userProvider
=
user
.
getProvider
();
if
(!
EMAIL_PROVIDER
.
equals
(
userProvider
))
{
throw
new
UserAlreadyExistsException
(
"An account with this email exists. Please sign in using "
+
userProvider
);
}
return
jwtService
.
generateToken
(
user
.
getId
());
}
String
accessToken
=
getAccessToken
(
googleAuthDTO
.
getServerAuthCode
());
LocalDate
userBirthdate
=
getUserBirthdate
(
accessToken
);
User
newUser
=
new
User
();
newUser
.
setEmail
(
email
);
newUser
.
setName
(
name
);
newUser
.
setPassword
(
null
);
newUser
.
setProvider
(
EMAIL_PROVIDER
);
newUser
.
setVerified
(
true
);
newUser
.
setRole
(
"USER"
);
newUser
.
setBirthdate
(
userBirthdate
);
User
user
=
userService
.
save
(
newUser
);
logger
.
info
(
"New user registered via Google authentication: {}"
,
email
);
return
jwtService
.
generateToken
(
user
.
getId
());
}
catch
(
UserAlreadyExistsException
e
)
{
throw
e
;
}
catch
(
Exception
e
)
{
logger
.
error
(
"Google authentication failed: {}"
,
e
.
getMessage
());
throw
new
ApiException
(
"Authentication failed"
);
}
}
GoogleIdTokenVerifier
createIdTokenVerifier
()
{
return
new
GoogleIdTokenVerifier
.
Builder
(
new
NetHttpTransport
(),
new
GsonFactory
())
.
setAudience
(
Collections
.
singletonList
(
googleClientId
))
.
build
();
}
public
GoogleIdToken
.
Payload
verifyIdToken
(
String
idTokenString
)
throws
Exception
{
GoogleAuthorizationCodeTokenRequest
createAuthorizationCodeTokenRequest
(
String
serverAuthCode
)
{
return
new
GoogleAuthorizationCodeTokenRequest
(
new
NetHttpTransport
(),
GsonFactory
.
getDefaultInstance
(),
"https://oauth2.googleapis.com/token"
,
googleClientId
,
googleClientSecret
,
serverAuthCode
,
""
);
}
GoogleIdToken
.
Payload
verifyIdToken
(
String
idTokenString
)
throws
IllegalArgumentException
,
InvalidCredentialsException
,
GeneralSecurityException
,
IOException
{
if
(
idTokenString
==
null
)
{
throw
new
IllegalArgumentException
(
"ID Token cannot be null"
);
}
...
...
@@ -63,59 +119,52 @@ public class GoogleAuthService extends AuthenticationService {
GoogleIdToken
idToken
=
verifier
.
verify
(
idTokenString
);
if
(
idToken
==
null
)
{
throw
new
Exception
(
"Invalid ID Token"
);
throw
new
InvalidCredentials
Exception
(
"Invalid ID Token"
);
}
return
idToken
.
getPayload
();
}
protected
GoogleAuthorizationCodeTokenRequest
createTokenRequest
(
String
tokenUrl
,
String
clientId
,
String
clientSecret
)
{
return
new
GoogleAuthorizationCodeTokenRequest
(
new
NetHttpTransport
(),
GsonFactory
.
getDefaultInstance
(),
tokenUrl
,
clientId
,
clientSecret
,
""
,
""
);
protected
URL
createURL
(
String
urlString
)
throws
IOException
{
URI
uri
=
URI
.
create
(
urlString
);
return
uri
.
toURL
();
}
public
String
getAccessToken
(
String
serverAuthCode
)
throws
IOException
{
TokenResponse
tokenResponse
=
createTokenRequest
(
"https://oauth2.googleapis.com/token"
,
googleClientId
,
googleClientSecret
)
.
setCode
(
serverAuthCode
)
String
getAccessToken
(
String
serverAuthCode
)
throws
IOException
{
TokenResponse
tokenResponse
=
createAuthorizationCodeTokenRequest
(
serverAuthCode
)
.
execute
();
return
tokenResponse
.
getAccessToken
();
}
protected
URL
createURL
(
String
urlString
)
throws
IOException
{
return
new
URL
(
urlString
);
}
public
String
fetchUserData
(
String
accessToken
,
String
personFields
)
throws
IOException
{
String
apiUrl
=
PEOPLE_API_BASE_URL
+
"?personFields="
+
personFields
;
URL
url
=
createURL
(
apiUrl
);
HttpURLConnection
conn
=
(
HttpURLConnection
)
url
.
openConnection
();
String
fetchUserData
(
String
accessToken
)
throws
IOException
{
try
{
conn
.
setRequestMethod
(
"GET"
);
conn
.
setRequestProperty
(
"Authorization"
,
"Bearer "
+
accessToken
);
conn
.
setRequestProperty
(
"Accept"
,
"application/json"
);
int
responseCode
=
conn
.
getResponseCode
();
if
(
responseCode
==
HttpURLConnection
.
HTTP_OK
)
{
return
readResponse
(
conn
.
getInputStream
());
}
else
{
throw
new
ApiException
(
"Error fetching data from Google API"
,
responseCode
);
String
apiUrl
=
PEOPLE_API_BASE_URL
+
"?personFields="
+
GoogleAuthService
.
BIRTHDAY
;
URL
url
=
createURL
(
apiUrl
);
HttpURLConnection
conn
=
(
HttpURLConnection
)
url
.
openConnection
();
try
{
conn
.
setRequestMethod
(
"GET"
);
conn
.
setRequestProperty
(
"Authorization"
,
"Bearer "
+
accessToken
);
conn
.
setRequestProperty
(
"Accept"
,
"application/json"
);
int
responseCode
=
conn
.
getResponseCode
();
if
(
responseCode
==
HttpURLConnection
.
HTTP_OK
)
{
return
readResponse
(
conn
.
getInputStream
());
}
else
{
logger
.
error
(
"Error fetching data from Google API: HTTP {}"
,
responseCode
);
throw
new
ApiException
(
"Error fetching data from Google API"
);
}
}
finally
{
conn
.
disconnect
();
}
}
finally
{
conn
.
disconnect
();
}
catch
(
MalformedURLException
e
)
{
logger
.
error
(
"Invalid API URL: {}"
,
e
.
getMessage
());
throw
new
IllegalArgumentException
(
"Invalid API URL"
,
e
);
}
}
private
String
readResponse
(
InputStream
inputStream
)
throws
IOException
{
try
(
BufferedReader
reader
=
new
BufferedReader
(
new
InputStreamReader
(
inputStream
)))
{
StringBuilder
response
=
new
StringBuilder
();
...
...
@@ -127,53 +176,20 @@ public class GoogleAuthService extends AuthenticationService {
}
}
public
LocalDate
getUserBirthdate
(
String
accessToken
)
throws
IOException
{
String
response
=
fetchUserData
(
accessToken
,
"birthdays"
);
LocalDate
getUserBirthdate
(
String
accessToken
)
throws
IOException
{
String
response
=
fetchUserData
(
accessToken
);
return
extractBirthday
(
response
);
}
public
String
authenticate
(
GoogleAuthDTO
googleAuthDTO
)
throws
Exception
{
GoogleIdToken
.
Payload
payload
=
verifyIdToken
(
googleAuthDTO
.
getIdToken
());
String
email
=
payload
.
getEmail
();
String
name
=
(
String
)
payload
.
get
(
"name"
);
Optional
<
User
>
existingUser
=
Optional
.
ofNullable
(
super
.
getUserRepository
().
findByEmail
(
email
));
if
(
existingUser
.
isPresent
())
{
User
user
=
existingUser
.
get
();
String
userProvider
=
user
.
getProvider
();
if
(!
EMAIL_PROVIDER
.
equals
(
userProvider
))
{
throw
new
UserAlreadyExistsException
(
"An account with this email exists. Please sign in using "
+
userProvider
);
}
return
super
.
generateJwtToken
(
user
.
getId
());
}
String
accessToken
=
getAccessToken
(
googleAuthDTO
.
getServerAuthCode
());
LocalDate
userBirthdate
=
getUserBirthdate
(
accessToken
);
User
newUser
=
new
User
();
newUser
.
setEmail
(
email
);
newUser
.
setName
(
name
);
newUser
.
setPassword
(
null
);
newUser
.
setProvider
(
"GOOGLE"
);
newUser
.
setVerified
(
true
);
newUser
.
setRole
(
"USER"
);
newUser
.
setBirthdate
(
userBirthdate
);
User
user
=
super
.
getUserRepository
().
save
(
newUser
);
return
super
.
generateJwtToken
(
user
.
getId
());
}
LocalDate
extractBirthday
(
String
jsonResponse
)
{
JsonElement
rootElement
=
JsonParser
.
parseString
(
jsonResponse
);
JsonObject
rootObj
=
rootElement
.
getAsJsonObject
();
if
(!
rootObj
.
has
(
"birthdays"
))
{
if
(!
rootObj
.
has
(
BIRTHDAY
))
{
return
null
;
}
JsonArray
birthdaysArray
=
rootObj
.
getAsJsonArray
(
"birthdays"
);
JsonArray
birthdaysArray
=
rootObj
.
getAsJsonArray
(
BIRTHDAY
);
if
(
birthdaysArray
.
isEmpty
())
{
return
null
;
}
...
...
@@ -195,4 +211,4 @@ public class GoogleAuthService extends AuthenticationService {
return
LocalDate
.
of
(
Year
.
now
().
getValue
(),
month
,
day
);
}
}
}
\ No newline at end of file
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment