This commit is contained in:
annampak 2018-01-11 13:15:29 +02:00
commit 91eecde080
20 changed files with 210 additions and 29 deletions

View File

@ -186,6 +186,13 @@
<version>1.0.0.RELEASE</version>
</dependency>
<!-- tweeter login-->
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-twitter</artifactId>
<version>1.1.2.RELEASE</version>
</dependency>
<!-- Various libs -->
<dependency>

View File

@ -1,13 +1,16 @@
package eu.eudat.controllers;
import eu.eudat.exceptions.UnauthorisedException;
import eu.eudat.models.login.Credentials;
import eu.eudat.models.helpers.responses.ResponseItem;
import eu.eudat.models.login.LoginInfo;
import eu.eudat.models.security.Principal;
import eu.eudat.security.CustomAuthenticationProvider;
import eu.eudat.security.validators.twitter.TwitterTokenValidator;
import eu.eudat.services.AuthenticationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.social.oauth1.OAuthToken;
import org.springframework.web.bind.annotation.*;
import javax.transaction.Transactional;
@ -20,23 +23,43 @@ import javax.transaction.Transactional;
@RequestMapping(value = "/auth")
public class Login {
@Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
@Autowired
private AuthenticationService authenticationService;
private TwitterTokenValidator twitterTokenValidator;
@Autowired
public Login(CustomAuthenticationProvider customAuthenticationProvider, AuthenticationService authenticationService, TwitterTokenValidator twitterTokenValidator) {
this.customAuthenticationProvider = customAuthenticationProvider;
this.authenticationService = authenticationService;
this.twitterTokenValidator = twitterTokenValidator;
}
@Transactional
@RequestMapping(method = RequestMethod.POST, value = { "/externallogin" }, consumes = "application/json", produces="application/json")
public @ResponseBody ResponseItem<Principal> googleLogin(@RequestBody LoginInfo credentials) {
try {
return new ResponseItem<Principal>().payload(customAuthenticationProvider.authenticate(credentials)).status(HttpStatus.OK);
} catch (Exception ex) {
}catch (UnauthorisedException ex){
throw ex;
}
catch (Exception ex) {
ex.printStackTrace();
return new ResponseItem<Principal>().status(HttpStatus.BAD_REQUEST).message(ex.getMessage());
}
}
@RequestMapping(method = RequestMethod.GET, value = { "/twitterRequestToken" }, produces="application/json")
public @ResponseBody ResponseItem<OAuthToken> twitterRequestToken() {
try {
return new ResponseItem<OAuthToken>().payload(this.twitterTokenValidator.getRequestToken()).status(HttpStatus.OK);
} catch (Exception ex) {
ex.printStackTrace();
return new ResponseItem<OAuthToken>().status(HttpStatus.BAD_REQUEST).message(ex.getMessage());
}
}
@RequestMapping(method = RequestMethod.POST, value = { "/me" }, consumes = "application/json", produces="application/json")
public @ResponseBody ResponseItem<Principal> authMe(Principal principal) {
try {

View File

@ -8,6 +8,8 @@ import eu.eudat.security.validators.TokenValidatorFactoryImpl;
public class LoginInfo {
private String ticket;
private TokenValidatorFactoryImpl.LoginProvider provider;
private Object data;
public String getTicket() {
return ticket;
}
@ -23,4 +25,12 @@ public class LoginInfo {
public void setProvider(Integer provider) {
this.provider = TokenValidatorFactoryImpl.LoginProvider.fromInteger(provider);
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}

View File

@ -25,7 +25,7 @@ public class CustomAuthenticationProvider {
public Principal authenticate(LoginInfo credentials) throws AuthenticationException, GeneralSecurityException {
String token = credentials.getTicket();
try {
Principal principal = this.tokenValidatorFactory.getProvider(credentials.getProvider()).validateToken(token);
Principal principal = this.tokenValidatorFactory.getProvider(credentials.getProvider()).validateToken(credentials);
return principal;
} catch (NonValidTokenException e) {
e.printStackTrace();

View File

@ -2,6 +2,7 @@ package eu.eudat.security.validators;
import eu.eudat.entities.UserInfo;
import eu.eudat.exceptions.NonValidTokenException;
import eu.eudat.models.login.LoginInfo;
import eu.eudat.models.security.Principal;
import java.io.IOException;
@ -9,6 +10,6 @@ import java.security.GeneralSecurityException;
public interface TokenValidator {
Principal validateToken(String token) throws NonValidTokenException, IOException, GeneralSecurityException;
Principal validateToken(LoginInfo credentials) throws NonValidTokenException, IOException, GeneralSecurityException;
}

View File

@ -3,6 +3,7 @@ package eu.eudat.security.validators;
import eu.eudat.security.validators.facebook.FacebookTokenValidator;
import eu.eudat.security.validators.google.GoogleTokenValidator;
import eu.eudat.security.validators.linkedin.LinkedInTokenValidator;
import eu.eudat.security.validators.twitter.TwitterTokenValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -43,11 +44,13 @@ public class TokenValidatorFactoryImpl implements TokenValidatorFactory{
private GoogleTokenValidator googleTokenValidator;
private FacebookTokenValidator facebookTokenValidator;
private LinkedInTokenValidator linkedInTokenValidator;
private TwitterTokenValidator twitterTokenValidator;
@Autowired
public TokenValidatorFactoryImpl(GoogleTokenValidator googleTokenValidator, FacebookTokenValidator facebookTokenValidator,LinkedInTokenValidator linkedInTokenValidator) {
public TokenValidatorFactoryImpl(GoogleTokenValidator googleTokenValidator, FacebookTokenValidator facebookTokenValidator,LinkedInTokenValidator linkedInTokenValidator,TwitterTokenValidator twitterTokenValidator) {
this.googleTokenValidator = googleTokenValidator;
this.facebookTokenValidator = facebookTokenValidator;
this.linkedInTokenValidator = linkedInTokenValidator;
this.twitterTokenValidator = twitterTokenValidator;
}
public TokenValidator getProvider(LoginProvider provider) {
@ -58,6 +61,8 @@ public class TokenValidatorFactoryImpl implements TokenValidatorFactory{
return this.facebookTokenValidator;
case LINKEDIN:
return this.linkedInTokenValidator;
case TWITTER:
return this.twitterTokenValidator;
default:
throw new RuntimeException("Login Provider Not Implemented");
}

View File

@ -7,7 +7,9 @@ import eu.eudat.entities.Credential;
import eu.eudat.entities.UserInfo;
import eu.eudat.entities.UserToken;
import eu.eudat.exceptions.NonValidTokenException;
import eu.eudat.exceptions.UnauthorisedException;
import eu.eudat.models.criteria.UserInfoCriteria;
import eu.eudat.models.login.LoginInfo;
import eu.eudat.models.loginprovider.LoginProviderUser;
import eu.eudat.models.security.Principal;
import eu.eudat.security.validators.TokenValidator;
@ -50,14 +52,15 @@ public class FacebookTokenValidator implements TokenValidator {
}
@Override
public Principal validateToken(String token) throws NonValidTokenException, IOException, GeneralSecurityException {
User profile = getFacebookUser(token);
public Principal validateToken(LoginInfo credentials) throws NonValidTokenException, IOException, GeneralSecurityException {
User profile = getFacebookUser(credentials.getTicket());
LoginProviderUser user = new LoginProviderUser();
if(profile.getEmail() == null ) throw new UnauthorisedException("Cannot login user.Facebook account did not provide email");
user.setEmail(profile.getEmail());
user.setIsVerified(profile.isVerified());
user.setName(profile.getName());
user.setProvider(TokenValidatorFactoryImpl.LoginProvider.FACEBOOK);
user.setSecret(token);
user.setSecret(credentials.getTicket());
return this.authenticationService.Touch(user);
}

View File

@ -61,12 +61,12 @@ public class GoogleTokenValidator implements TokenValidator {
}
@Override
public eu.eudat.models.security.Principal validateToken(String token) throws NonValidTokenException, IOException, GeneralSecurityException {
public eu.eudat.models.security.Principal validateToken(LoginInfo credentials) throws NonValidTokenException, IOException, GeneralSecurityException {
GoogleIdToken idToken = this.verifyUserAndGetUser(token);
GoogleIdToken idToken = this.verifyUserAndGetUser(credentials.getTicket());
Payload payload = idToken.getPayload();
LoginProviderUser user = new LoginProviderUser();
user.setSecret(token);
user.setSecret(credentials.getTicket());
user.setProvider(TokenValidatorFactoryImpl.LoginProvider.GOOGLE);
user.setName((String)payload.get("name"));
user.setEmail(payload.getEmail());

View File

@ -1,6 +1,8 @@
package eu.eudat.security.validators.linkedin;
import eu.eudat.exceptions.NonValidTokenException;
import eu.eudat.exceptions.UnauthorisedException;
import eu.eudat.models.login.LoginInfo;
import eu.eudat.models.loginprovider.LoginProviderUser;
import eu.eudat.models.security.Principal;
import eu.eudat.security.validators.TokenValidator;
@ -31,21 +33,24 @@ public class LinkedInTokenValidator implements TokenValidator {
private LinkedInServiceProvider linkedInServiceProvider;
@Autowired
public LinkedInTokenValidator(Environment environment,ApiContext apiContext,AuthenticationService authenticationService) {
public LinkedInTokenValidator(Environment environment, ApiContext apiContext, AuthenticationService authenticationService) {
this.environment = environment;
this.apiContext= apiContext;
this.apiContext = apiContext;
this.authenticationService = authenticationService;
this.linkedInServiceProvider = new LinkedInServiceProvider(this.environment.getProperty("linkedin.login.clientId"), this.environment.getProperty("linkedin.login.clientSecret"));
}
@Override
public Principal validateToken(String token) throws NonValidTokenException, IOException, GeneralSecurityException {
AccessGrant accessGrant =this.linkedInServiceProvider.getOAuthOperations().exchangeForAccess(token,"http://localhost:4200/login/linkedin",null);
public Principal validateToken(LoginInfo credentials) throws NonValidTokenException, IOException, GeneralSecurityException {
AccessGrant accessGrant = this.linkedInServiceProvider.getOAuthOperations().exchangeForAccess(credentials.getTicket(), this.environment.getProperty("linkedin.login.redirect_uri"), null);
LinkedIn linkedInService = this.linkedInServiceProvider.getApi(accessGrant.getAccessToken());
LinkedInProfile linkedInProfile = linkedInService.profileOperations().getUserProfile();
LoginProviderUser user = new LoginProviderUser();
if (user.getEmail() == null) throw new UnauthorisedException("Cannot login user.LinkedIn account did not provide email");
user.setEmail(linkedInProfile.getEmailAddress());
user.setIsVerified(true); //TODO
user.setName(linkedInProfile.getFirstName()+" "+linkedInProfile.getLastName());
user.setName(linkedInProfile.getFirstName() + " " + linkedInProfile.getLastName());
user.setProvider(TokenValidatorFactoryImpl.LoginProvider.LINKEDIN);
user.setSecret(accessGrant.getAccessToken());
return this.authenticationService.Touch(user);

View File

@ -0,0 +1,71 @@
package eu.eudat.security.validators.twitter;
import eu.eudat.exceptions.NonValidTokenException;
import eu.eudat.exceptions.UnauthorisedException;
import eu.eudat.models.login.LoginInfo;
import eu.eudat.models.loginprovider.LoginProviderUser;
import eu.eudat.models.security.Principal;
import eu.eudat.security.validators.TokenValidator;
import eu.eudat.security.validators.TokenValidatorFactoryImpl;
import eu.eudat.services.ApiContext;
import eu.eudat.services.AuthenticationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.social.linkedin.api.LinkedIn;
import org.springframework.social.linkedin.api.LinkedInProfile;
import org.springframework.social.linkedin.connect.LinkedInServiceProvider;
import org.springframework.social.oauth1.AuthorizedRequestToken;
import org.springframework.social.oauth1.OAuthToken;
import org.springframework.social.oauth2.AccessGrant;
import org.springframework.social.twitter.api.TwitterProfile;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
import org.springframework.social.twitter.connect.TwitterServiceProvider;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Map;
/**
* Created by ikalyvas on 1/11/2018.
*/
@Component("twitterTokenValidator")
public class TwitterTokenValidator implements TokenValidator {
private Environment environment;
private ApiContext apiContext;
private AuthenticationService authenticationService;
private TwitterServiceProvider twitterServiceProvider;
@Autowired
public TwitterTokenValidator(Environment environment, ApiContext apiContext, AuthenticationService authenticationService) {
this.environment = environment;
this.apiContext = apiContext;
this.authenticationService = authenticationService;
this.twitterServiceProvider = new TwitterServiceProvider(this.environment.getProperty("twitter.login.clientId"), this.environment.getProperty("twitter.login.clientSecret"));
}
@Override
public Principal validateToken(LoginInfo credentials) throws NonValidTokenException, IOException, GeneralSecurityException {
String verifier = (String) credentials.getData();
OAuthToken oAuthToken = new OAuthToken(credentials.getTicket(),verifier);
AuthorizedRequestToken authorizedRequestToken = new AuthorizedRequestToken(oAuthToken,verifier);
OAuthToken finalOauthToken = this.twitterServiceProvider.getOAuthOperations().exchangeForAccessToken(authorizedRequestToken,null);
TwitterTemplate twitterTemplate = new TwitterTemplate(this.environment.getProperty("twitter.login.clientId"), this.environment.getProperty("twitter.login.clientSecret"),finalOauthToken.getValue(),finalOauthToken.getSecret());
TwitterProfile profile = this.twitterServiceProvider.getApi(finalOauthToken.getValue(),finalOauthToken.getSecret()).userOperations().getUserProfile();
LoginProviderUser user = new LoginProviderUser();
Map values = twitterTemplate.getRestTemplate().getForObject("https://api.twitter.com/1.1/account/verify_credentials.json?include_email=true", Map.class);
if(values.get("email") == null) throw new UnauthorisedException("Cannot login user.Twitter account did not provide email");
user.setEmail((String) values.get("email"));
user.setIsVerified(true); //TODO
user.setName(profile.getName());
user.setProvider(TokenValidatorFactoryImpl.LoginProvider.TWITTER);
user.setSecret(finalOauthToken.getValue());
return this.authenticationService.Touch(user);
}
public OAuthToken getRequestToken() {
return this.twitterServiceProvider.getOAuthOperations().fetchRequestToken(this.environment.getProperty("twitter.login.redirect_uri"), null);
}
}

View File

@ -35,9 +35,15 @@ facebook.login.clientSecret = 522a847f05c873d0222c85109e24f55a
facebook.login.namespace = eudat
########################GOOGLE LOGIN Properties#############################
google.login.clientId = 524432312250-sc9qsmtmbvlv05r44onl6l93ia3k9deo.apps.googleusercontent.com
########################LINKEDIN LOGIN Properties#############################
########################LINKEDIN LOGIN Properties#############################HiR4hQH9HNubKC5iKQy0l4mAZ
linkedin.login.clientId = 86bl8vfk77clh9
linkedin.login.clientSecret = 2OCO9e3wKylW05Tt
linkedin.login.redirect_uri = 2OCO9e3wKylW05Tt
########################LINKEDIN LOGIN Properties#############################
twitter.login.clientId = HiR4hQH9HNubKC5iKQy0l4mAZ
twitter.login.clientSecret = 9KZHgkqUO2QFnELSL14jeUvfUacWX23rqD8OW8X0xoRDXOSfKH
twitter.login.redirect_uri = http://localhost:4200/login/twitter
########################Persistence/Hibernate/Batch##############################
#persistence.hibernate.jdbc.batch_size = 30
#persistence.hibernate.order_inserts = true

View File

@ -101,7 +101,8 @@ import { AutocompleteComponent } from './shared/components/autocomplete/autocomp
LoginOptions.facebookOauth,
LoginOptions.googleOauth,
LoginOptions.nativeLogin,
LoginOptions.linkedInOauth
LoginOptions.linkedInOauth,
LoginOptions.twitterOauth
],
facebookConfiguration: { clientId: "110586756143149" },
googleConfiguration: { clientId: '524432312250-sc9qsmtmbvlv05r44onl6l93ia3k9deo.apps.googleusercontent.com' },
@ -111,7 +112,8 @@ import { AutocompleteComponent } from './shared/components/autocomplete/autocomp
redirectUri: HostConfiguration.App + "login/linkedin",
accessTokenUri: "https://www.linkedin.com/oauth/v2/accessToken",
clientSecret: "2OCO9e3wKylW05Tt"
}
},
twitterConfiguration: { clientId: "HiR4hQH9HNubKC5iKQy0l4mAZ", oauthUrl: "https://api.twitter.com/oauth/authenticate" }
}),
HttpModule,
HttpClientModule,

View File

@ -8,4 +8,5 @@ export enum LoginProviders {
export class LoginInfo {
public ticket: string;
public provider: LoginProviders;
public data?: any;
}

View File

@ -1,3 +1,4 @@
import { TwitterLoginComponent } from './login/twitter-login/twitter-login.component';
import { SnackBarNotificationComponent } from '../shared/components/notificaiton/snack-bar-notification.component';
import { LinkedInLoginComponent } from './login/linkedin-login/linkedin-login.component';
import { LoginRoutes } from './login.routes';
@ -17,11 +18,13 @@ import { CommonModule } from '@angular/common';
],
declarations: [
LoginComponent,
LinkedInLoginComponent
LinkedInLoginComponent,
TwitterLoginComponent
],
exports: [
LoginComponent,
LinkedInLoginComponent
LinkedInLoginComponent,
TwitterLoginComponent
],
providers: [LoginService]
})

View File

@ -1,11 +1,12 @@
import { TwitterLoginComponent } from './login/twitter-login/twitter-login.component';
import { LinkedInLoginComponent } from './login/linkedin-login/linkedin-login.component';
import { LoginComponent } from './login/login.component';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{ path: '', component: LoginComponent },
{ path: 'linkedin', component: LinkedInLoginComponent }
{ path: 'login', component: LoginComponent },
{ path: 'login/linkedin', component: LinkedInLoginComponent },
{ path: 'login/twitter', component: TwitterLoginComponent }
];
export const LoginRoutes = RouterModule.forChild(routes);

View File

@ -15,7 +15,7 @@
<button *ngIf="hasFacebookOauth()" mat-icon-button (click)="facebookLogin()">
<i class="fa fa-facebook-square"></i>
</button>
<button *ngIf="hasTwitterOauth()" mat-icon-button>
<button *ngIf="hasTwitterOauth()" mat-icon-button (click)="twitterLogin()">
<i class="fa fa-twitter"></i>
</button>
</div>

View File

@ -36,6 +36,10 @@ export class LoginComponent implements OnInit {
this.loginService.linkedInInitialiseLogin();
}
public twitterLogin() {
this.loginService.twitterInitialiseLogin();
}
public hasFacebookOauth(): boolean {
return this.loginService.hasProvider(LoginOptions.facebookOauth);
}

View File

@ -1,9 +1,24 @@
import { LoginService } from '../../utilties/login-service';
import { ActivatedRoute, Router } from '@angular/router'
import { Component } from '@angular/core'
@Component({
selector: 'twitter-login',
templateUrl: './twitter-login.component.html',
styleUrls: ['./login.component.scss']
})
export class TwitterLoginComponent {
constructor(
private router: Router,
private route: ActivatedRoute,
private loginService: LoginService
) {
}
ngOnInit(): void {
this.route.queryParams.subscribe((data: any) => {
if (!data["oauth_token"] && !data["oauth_verifier"]) this.loginService.twitterAuthorize()
else this.loginService.twitterLogin(data["oauth_token"],data["oauth_verifier"])
})
}
}

View File

@ -9,6 +9,7 @@ export class GoogleLoginConfiguration extends LoginProviderConfiguration {
}
export class TwitterLoginConfiguration extends LoginProviderConfiguration {
public oauthUrl: string
}
export class LinkedInConfiguration extends LoginProviderConfiguration {

View File

@ -28,8 +28,8 @@ export class LoginService {
public snackBar: MatSnackBar,
public language: TranslateService,
private zone: NgZone,
private httpClient: HttpClient
@Optional() private config: LoginServiceConfiguration,
private httpClient: HttpClient,
@Optional() private config: LoginServiceConfiguration
) {
if (config) {
this.providers = config.loginProviders;
@ -145,6 +145,29 @@ export class LoginService {
)
}
/*
* TWITTER SIGN IN
*/
public twitterInitialiseLogin() {
this.router.navigate(["/login/twitter"])
}
public twitterAuthorize() {
let headers = new HttpHeaders();
headers = headers.set('Content-Type', 'application/json');
headers = headers.set('Accept', 'application/json');
this.httpClient.get(HostConfiguration.Server + 'auth/twitterRequestToken', { headers: headers }).subscribe((data: any) => {
window.location.href = this.config.twitterConfiguration.oauthUrl + "?oauth_token=" + data.payload.value
})
}
public twitterLogin(token: string, verifier: string) {
this.authService.login({ ticket: token, provider: LoginProviders.Twitter, data: verifier }).subscribe(
res => this.onLogInSuccess(res),
error => this.onLogInError(error)
)
}
/*
* LOGIN HANDLERS
*/