Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Genesys Backend
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
44
Issues
44
List
Boards
Labels
Service Desk
Milestones
Operations
Operations
Incidents
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Genesys PGR
Genesys Backend
Commits
d89a470e
Commit
d89a470e
authored
Dec 27, 2018
by
Maxym Borodenko
Committed by
Matija Obreza
Dec 27, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Google Sign-in authentication system
parent
5ccc1438
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
81 additions
and
127 deletions
+81
-127
pom.xml
pom.xml
+3
-11
src/main/java/org/genesys2/server/component/security/GoogleOAuthUtil.java
...g/genesys2/server/component/security/GoogleOAuthUtil.java
+34
-77
src/main/java/org/genesys2/server/mvc/GoogleSocialController.java
.../java/org/genesys2/server/mvc/GoogleSocialController.java
+41
-37
src/main/resources/content/language.properties
src/main/resources/content/language.properties
+1
-0
src/main/webapp/WEB-INF/decorator/1/menu.jsp
src/main/webapp/WEB-INF/decorator/1/menu.jsp
+1
-1
src/main/webapp/WEB-INF/jsp/login.jsp
src/main/webapp/WEB-INF/jsp/login.jsp
+1
-1
No files found.
pom.xml
View file @
d89a470e
...
...
@@ -76,7 +76,6 @@
<spring.security.oauth2.version>
2.3.3.RELEASE
</spring.security.oauth2.version>
<spring-security-jwt>
1.0.8.RELEASE
</spring-security-jwt>
<org.springframework.social-version>
1.1.4.RELEASE
</org.springframework.social-version>
<org.springframework.social-google-version>
1.0.0.RELEASE
</org.springframework.social-google-version>
<querydsl.version>
4.1.4
</querydsl.version>
<hibernate.version>
4.3.11.Final
</hibernate.version>
...
...
@@ -560,23 +559,16 @@
</dependency>
<dependency>
<groupId>
org.springframework.social
</groupId>
<artifactId>
spring-social-google
</artifactId>
<version>
${org.springframework.social-google-version}
</version>
<groupId>
com.google.api-client
</groupId>
<artifactId>
google-api-client
</artifactId>
<version>
1.27.0
</version>
</dependency>
<dependency>
<groupId>
org.springframework.social
</groupId>
<artifactId>
spring-social-web
</artifactId>
<version>
${org.springframework.social-version}
</version>
</dependency>
<dependency>
<groupId>
org.springframework.social
</groupId>
<artifactId>
spring-social-core
</artifactId>
<version>
${org.springframework.social-version}
</version>
</dependency>
<!--Test dependencies -->
<dependency>
<groupId>
org.hamcrest
</groupId>
...
...
src/main/java/org/genesys2/server/component/security/GoogleOAuthUtil.java
View file @
d89a470e
/*
*
* Copyright 201
4
Global Crop Diversity Trust
/*
* Copyright 201
8
Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
...
...
@@ -12,28 +12,23 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
/
*/
package
org.genesys2.server.component.security
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.UUID
;
import
javax.inject.Named
;
import
javax.servlet.http.HttpServletRequest
;
import
org.apache.http.HttpResponse
;
import
org.apache.http.NameValuePair
;
import
org.apache.http.client.entity.UrlEncodedFormEntity
;
import
org.apache.http.client.methods.HttpPost
;
import
org.apache.http.client.utils.URLEncodedUtils
;
import
org.apache.http.impl.client.CloseableHttpClient
;
import
org.apache.http.impl.client.HttpClientBuilder
;
import
org.apache.http.message.BasicNameValuePair
;
import
com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeRequestUrl
;
import
com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeTokenRequest
;
import
com.google.api.client.googleapis.auth.oauth2.GoogleIdToken
;
import
com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse
;
import
com.google.api.client.http.javanet.NetHttpTransport
;
import
com.google.api.client.json.jackson2.JacksonFactory
;
import
org.genesys.blocks.security.UserException
;
import
org.genesys.blocks.security.model.BasicUser
;
import
org.genesys2.server.model.impl.User
;
...
...
@@ -41,6 +36,7 @@ import org.genesys2.server.service.UserService;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.core.Authentication
;
...
...
@@ -48,19 +44,13 @@ import org.springframework.security.core.context.SecurityContextHolder;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.core.userdetails.UserDetailsService
;
import
org.springframework.security.core.userdetails.UsernameNotFoundException
;
import
org.springframework.social.google.api.plus.Person
;
import
org.springframework.stereotype.Component
;
import
com.fasterxml.jackson.databind.JsonNode
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
@Component
public
class
GoogleOAuthUtil
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
GoogleOAuthUtil
.
class
);
public
static
final
String
LOCAL_GOOGLEAUTH_PATH
=
"/google/auth"
;
private
ObjectMapper
mapper
=
new
ObjectMapper
();
@Value
(
"${base.url}"
)
private
String
baseUrl
;
...
...
@@ -74,64 +64,34 @@ public class GoogleOAuthUtil {
private
UserService
userService
;
@Autowired
@
Named
(
"authUserDetailsService"
)
@
Qualifier
(
"authUserDetailsService"
)
private
UserDetailsService
userDetailsService
;
public
String
exchangeForAccessToken
(
HttpServletRequest
request
)
throws
IOException
{
final
CloseableHttpClient
httpclient
=
HttpClientBuilder
.
create
().
build
();
try
{
final
HttpPost
httppost
=
new
HttpPost
(
"https://accounts.google.com/o/oauth2/token"
);
final
List
<
NameValuePair
>
params
=
new
ArrayList
<>();
params
.
add
(
new
BasicNameValuePair
(
"code"
,
request
.
getParameter
(
"code"
)));
params
.
add
(
new
BasicNameValuePair
(
"client_id"
,
googleApiClientId
));
params
.
add
(
new
BasicNameValuePair
(
"client_secret"
,
secret
));
params
.
add
(
new
BasicNameValuePair
(
"redirect_uri"
,
baseUrl
+
LOCAL_GOOGLEAUTH_PATH
));
params
.
add
(
new
BasicNameValuePair
(
"grant_type"
,
"authorization_code"
));
params
.
add
(
new
BasicNameValuePair
(
"scope"
,
""
));
httppost
.
setEntity
(
new
UrlEncodedFormEntity
(
params
,
"UTF-8"
));
final
HttpResponse
response
=
httpclient
.
execute
(
httppost
);
final
BufferedReader
reader
=
new
BufferedReader
(
new
InputStreamReader
(
response
.
getEntity
().
getContent
(),
"UTF-8"
));
final
StringBuilder
builder
=
new
StringBuilder
();
for
(
String
line
=
null
;
(
line
=
reader
.
readLine
())
!=
null
;)
{
builder
.
append
(
line
).
append
(
"\n"
);
}
JsonNode
json
=
mapper
.
readTree
(
builder
.
toString
());
return
json
.
has
(
"access_token"
)
?
json
.
get
(
"access_token"
).
textValue
()
:
null
;
}
finally
{
httpclient
.
close
();
}
public
GoogleTokenResponse
exchangeForAccessToken
(
HttpServletRequest
request
)
throws
IOException
{
// Exchange auth code for access token
return
new
GoogleAuthorizationCodeTokenRequest
(
new
NetHttpTransport
(),
JacksonFactory
.
getDefaultInstance
(),
"https://www.googleapis.com/oauth2/v4/token"
,
googleApiClientId
,
secret
,
request
.
getParameter
(
"code"
),
baseUrl
+
LOCAL_GOOGLEAUTH_PATH
).
execute
();
}
public
String
getAuthenticationUrl
()
{
// google.auth.url=https://accounts.google.com/o/oauth2/auth?redirect_uri=http://localhost:8080/g/auth&response_type=code&client_id=12345-hfp8qjfeqaefpitbc707uluuh8vq65k7.apps.googleusercontent.com&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.login+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.me+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&approval_prompt=auto&access_type=online&include_granted_scopes=true
final
List
<
NameValuePair
>
parameters
=
new
ArrayList
<
NameValuePair
>();
parameters
.
add
(
new
BasicNameValuePair
(
"redirect_uri"
,
baseUrl
+
LOCAL_GOOGLEAUTH_PATH
));
parameters
.
add
(
new
BasicNameValuePair
(
"response_type"
,
"code"
));
parameters
.
add
(
new
BasicNameValuePair
(
"client_id"
,
googleApiClientId
));
parameters
.
add
(
new
BasicNameValuePair
(
"approval_prompt"
,
"auto"
));
parameters
.
add
(
new
BasicNameValuePair
(
"access_type"
,
"online"
));
parameters
.
add
(
new
BasicNameValuePair
(
"include_granted_scopes"
,
"true"
));
// Google+
// "https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"));
// Only basic:
parameters
.
add
(
new
BasicNameValuePair
(
"scope"
,
"https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email"
));
final
String
query
=
URLEncodedUtils
.
format
(
parameters
,
"UTF-8"
);
return
"https://accounts.google.com/o/oauth2/auth?"
+
query
;
return
new
GoogleAuthorizationCodeRequestUrl
(
googleApiClientId
,
baseUrl
+
LOCAL_GOOGLEAUTH_PATH
,
Arrays
.
asList
(
"https://www.googleapis.com/auth/userinfo.email"
,
"https://www.googleapis.com/auth/userinfo.profile"
))
.
setResponseTypes
(
Collections
.
singletonList
(
"code"
))
.
setApprovalPrompt
(
"auto"
).
build
();
}
public
Authentication
googleAuthentication
(
Person
userInfo
)
{
public
Authentication
googleAuthentication
(
GoogleIdToken
.
Payload
tokenPayload
)
{
try
{
final
UserDetails
userDetails
=
userDetailsService
.
loadUserByUsername
(
userInfo
.
getAccoun
tEmail
());
final
UserDetails
userDetails
=
userDetailsService
.
loadUserByUsername
(
tokenPayload
.
ge
tEmail
());
if
(!(
userDetails
.
isEnabled
()
&&
userDetails
.
isAccountNonExpired
()
&&
userDetails
.
isAccountNonLocked
()
&&
userDetails
.
isCredentialsNonExpired
()))
{
LOG
.
warn
(
"Google login canceled: Account currently not available: {}"
,
userInfo
.
getAccoun
tEmail
());
LOG
.
warn
(
"Google login canceled: Account currently not available: {}"
,
tokenPayload
.
ge
tEmail
());
return
null
;
}
...
...
@@ -140,18 +100,15 @@ public class GoogleOAuthUtil {
return
authentication
;
}
catch
(
final
UsernameNotFoundException
e
)
{
LOG
.
warn
(
"Authentication with Google
+ failed: No such user {}"
,
userInfo
.
getAccoun
tEmail
());
LOG
.
warn
(
"Authentication with Google
failed: No such user {}"
,
tokenPayload
.
ge
tEmail
());
return
null
;
}
}
public
User
extractUserFromGoogle
Profile
(
Person
userInfo
)
throws
UserException
{
public
User
extractUserFromGoogle
TokenPayload
(
GoogleIdToken
.
Payload
tokenPayload
)
throws
UserException
{
User
user
=
null
;
try
{
user
=
userService
.
getUserByEmail
(
userInfo
.
getAccountEmail
());
if
(
user
==
null
){
throw
new
UsernameNotFoundException
(
"User not found"
);
}
user
=
(
User
)
userDetailsService
.
loadUserByUsername
(
tokenPayload
.
getEmail
());
if
(
user
.
getAccountType
()
==
BasicUser
.
AccountType
.
LOCAL
)
{
// account exists, change to {@link LoginType#GOOGLE}
LOG
.
info
(
"Changing account type to LoginType#GOOGLE"
);
...
...
@@ -159,7 +116,7 @@ public class GoogleOAuthUtil {
}
}
catch
(
UsernameNotFoundException
e
)
{
LOG
.
info
(
"Username not found, creating new Google account"
);
user
=
userService
.
createUser
(
userInfo
.
getAccountEmail
(),
userInfo
.
getDisplayName
(
),
null
,
BasicUser
.
AccountType
.
GOOGLE
);
user
=
userService
.
createUser
(
tokenPayload
.
getEmail
(),
(
String
)
tokenPayload
.
get
(
"name"
),
null
,
BasicUser
.
AccountType
.
GOOGLE
);
userService
.
userEmailValidated
(
UUID
.
fromString
(
user
.
getUuid
()));
}
return
user
;
...
...
src/main/java/org/genesys2/server/mvc/GoogleSocialController.java
View file @
d89a470e
/*
*
* Copyright 201
4
Global Crop Diversity Trust
/*
* Copyright 201
8
Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
...
...
@@ -12,12 +12,14 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
/
*/
package
org.genesys2.server.mvc
;
import
java.io.IOException
;
import
java.security.GeneralSecurityException
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.HashSet
;
import
java.util.Set
;
...
...
@@ -25,15 +27,21 @@ import javax.servlet.ServletException;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
org.genesys.blocks.security.NotUniqueUserException
;
import
com.google.api.client.googleapis.auth.oauth2.GoogleIdToken
;
import
com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload
;
import
com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier
;
import
com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse
;
import
com.google.api.client.http.javanet.NetHttpTransport
;
import
com.google.api.client.json.jackson2.JacksonFactory
;
import
org.genesys.blocks.security.UserException
;
import
org.genesys.blocks.security.service.PasswordPolicy.PasswordPolicyException
;
import
org.genesys2.server.component.security.GoogleOAuthUtil
;
import
org.genesys2.server.model.impl.User
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.security.authentication.BadCredentialsException
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.userdetails.UsernameNotFoundException
;
import
org.springframework.security.oauth2.provider.OAuth2Authentication
;
import
org.springframework.security.oauth2.provider.OAuth2Request
;
import
org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices
;
...
...
@@ -41,9 +49,6 @@ import org.springframework.security.web.authentication.AuthenticationFailureHand
import
org.springframework.security.web.authentication.AuthenticationSuccessHandler
;
import
org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler
;
import
org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler
;
import
org.springframework.social.google.api.Google
;
import
org.springframework.social.google.api.impl.GoogleTemplate
;
import
org.springframework.social.google.api.plus.Person
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.ui.Model
;
import
org.springframework.web.bind.annotation.RequestMapping
;
...
...
@@ -63,37 +68,31 @@ public class GoogleSocialController extends BaseController {
@Autowired
private
AuthorizationServerTokenServices
tokenServices
;
@Value
(
"${google.consumerKey}"
)
private
String
googleApiClientId
;
@RequestMapping
(
"/google/login"
)
public
void
redirectToGoogle
(
HttpServletResponse
response
)
throws
IOException
{
response
.
sendRedirect
(
googleOAuthUtil
.
getAuthenticationUrl
());
}
/**
* @throws PasswordPolicyException Shouldn't happen
* @throws NotUniqueUserException
* @throws UsernameNotFoundException
*/
@RequestMapping
(
GoogleOAuthUtil
.
LOCAL_GOOGLEAUTH_PATH
)
public
void
googleAuth
(
Model
model
,
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
IOException
,
ServletException
,
UserException
{
public
void
googleAuth
(
Model
model
,
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
IOException
,
ServletException
{
String
accessToken
=
null
;
try
{
accessToken
=
googleOAuthUtil
.
exchangeForAccessToken
(
request
);
}
catch
(
IOException
e
)
{
LOG
.
warn
(
e
.
getMessage
(),
e
);
}
GoogleTokenResponse
googleTokenResponse
=
googleOAuthUtil
.
exchangeForAccessToken
(
request
);
if
(
accessToken
==
null
)
{
if
(
googleTokenResponse
==
null
)
{
model
.
addAttribute
(
"error"
,
true
);
authFailureHandler
.
onAuthenticationFailure
(
request
,
response
,
new
BadCredentialsException
(
"Could not authenticate you with Google
+
"
));
authFailureHandler
.
onAuthenticationFailure
(
request
,
response
,
new
BadCredentialsException
(
"Could not authenticate you with Google"
));
return
;
}
final
Google
google
=
new
GoogleTemplate
(
accessToken
);
final
Person
userInfo
=
google
.
plusOperations
().
getGoogleProfile
();
googleOAuthUtil
.
extractUserFromGoogleProfile
(
userInfo
);
final
Authentication
authentication
=
googleOAuthUtil
.
googleAuthentication
(
userInfo
);
// Get profile info from ID token
GoogleIdToken
idToken
=
googleTokenResponse
.
parseIdToken
();
final
Authentication
authentication
=
googleOAuthUtil
.
googleAuthentication
(
idToken
.
getPayload
());
// Redirect to URL in session
authSuccessHandler
.
onAuthenticationSuccess
(
request
,
response
,
authentication
);
...
...
@@ -102,27 +101,32 @@ public class GoogleSocialController extends BaseController {
/**
* Google XHR auth.
*
* @param
accessToken the access
token
* @param
tokenId the user's ID
token
* @param clientId the client id
* @return the object
*/
@RequestMapping
(
value
=
"/google/verify-token"
,
method
=
RequestMethod
.
GET
)
@ResponseBody
public
Object
googleAuth
(
@RequestParam
(
"accessToken"
)
final
String
accessToken
,
@RequestParam
(
"clientId"
)
final
String
clientId
)
throws
UserException
{
final
Google
google
=
new
GoogleTemplate
(
accessToken
);
final
Person
userInfo
=
google
.
plusOperations
().
getGoogleProfile
();
public
Object
googleAuth
(
@RequestParam
(
"tokenId"
)
final
String
tokenId
,
@RequestParam
(
"clientId"
)
final
String
clientId
)
throws
UserException
,
IOException
,
GeneralSecurityException
{
User
user
=
googleOAuthUtil
.
extractUserFromGoogleProfile
(
userInfo
);
GoogleIdTokenVerifier
verifier
=
new
GoogleIdTokenVerifier
.
Builder
(
new
NetHttpTransport
(),
JacksonFactory
.
getDefaultInstance
())
.
setAudience
(
Collections
.
singletonList
(
googleApiClientId
)).
build
();
GoogleIdToken
googleIdToken
=
verifier
.
verify
(
tokenId
);
final
Set
<
String
>
scope
=
new
HashSet
<>(
Arrays
.
asList
(
"trust"
,
"read"
,
"write"
));
final
OAuth2Request
oAuth2Request
=
new
OAuth2Request
(
null
,
clientId
,
user
.
getAuthorities
(),
true
,
scope
,
null
,
null
,
null
,
null
);
if
(
googleIdToken
!=
null
)
{
Payload
payload
=
googleIdToken
.
getPayload
();
User
user
=
googleOAuthUtil
.
extractUserFromGoogleTokenPayload
(
payload
);
final
UsernamePasswordAuthenticationToken
authenticationToken
=
new
UsernamePasswordAuthenticationToken
(
user
,
null
,
user
.
getAuthorities
(
));
final
OAuth2Authentication
auth
=
new
OAuth2Authentication
(
oAuth2Request
,
authenticationToken
);
final
Set
<
String
>
scope
=
new
HashSet
<>(
Arrays
.
asList
(
"trust"
,
"read"
,
"write"
));
final
OAuth2Request
oAuth2Request
=
new
OAuth2Request
(
null
,
clientId
,
user
.
getAuthorities
(),
true
,
scope
,
null
,
null
,
null
,
null
);
return
tokenServices
.
createAccessToken
(
auth
);
final
UsernamePasswordAuthenticationToken
authenticationToken
=
new
UsernamePasswordAuthenticationToken
(
user
,
null
,
user
.
getAuthorities
());
final
OAuth2Authentication
auth
=
new
OAuth2Authentication
(
oAuth2Request
,
authenticationToken
);
return
tokenServices
.
createAccessToken
(
auth
);
}
else
{
throw
new
BadCredentialsException
(
"Could not authenticate you with Google"
);
}
}
}
src/main/resources/content/language.properties
View file @
d89a470e
...
...
@@ -41,6 +41,7 @@ login.register-now=Create an account
logout
=
Logout
login.forgot-password
=
Forgot password
login.with-google-plus
=
Login with Google+
login.with-google-sign-in
=
Login with Google
# Registration
registration.page.title
=
Create a user account
...
...
src/main/webapp/WEB-INF/decorator/1/menu.jsp
View file @
d89a470e
...
...
@@ -167,7 +167,7 @@
<spring:message
code=
"login.login-button"
/>
</button>
<span
class=
"or"
>
-
</span>
<a
href=
"
<c:url
value=
"/google/login"
/>
"
class=
"btn btn-default google-signin"
>
<spring:message
code=
"login.with-google-
plus
"
/>
<a
href=
"
<c:url
value=
"/google/login"
/>
"
class=
"btn btn-default google-signin"
>
<spring:message
code=
"login.with-google-
sign-in
"
/>
</a>
<a
href=
"
<c:url
value=
"/registration"
/>
"
class=
"btn btn-default"
>
<spring:message
code=
"login.register-now"
/>
</a>
<!-- CSRF protection -->
...
...
src/main/webapp/WEB-INF/jsp/login.jsp
View file @
d89a470e
...
...
@@ -43,7 +43,7 @@
<div
class=
"form-group transparent"
>
<div
class=
"col-lg-offset-2 col-lg-10 col-md-offset-3 col-md-9 col-sm-offset-3 col-sm-9 col-xs-12"
>
<input
type=
"submit"
value=
"
<spring:message
code=
"login.login-button"
/>
"
class=
"btn btn-primary"
/>
<a
href=
"
<c:url
value=
"/google/login"
/>
"
class=
"btn btn-default google-signin"
><spring:message
code=
"login.with-google-
plus
"
/></a>
<a
href=
"
<c:url
value=
"/google/login"
/>
"
class=
"btn btn-default google-signin"
><spring:message
code=
"login.with-google-
sign-in
"
/></a>
<a
href=
"
<c:url
value=
"/registration"
/>
"
id=
"registration"
class=
"btn btn-default"
><spring:message
code=
"login.register-now"
/></a>
<a
href=
"
<c:url
value=
"/profile/forgot-password"
/>
"
id=
"forgot-password"
class=
"btn btn-default"
><spring:message
code=
"login.forgot-password"
/></a>
</div>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment