Skip to content

Commit

Permalink
linkedin functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
kh77 committed Mar 29, 2021
1 parent d591bcc commit 68216bb
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 7 deletions.
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,15 @@
- Google PlayGround
- https://developers.google.com/oauthplayground/
- Scope : openid email profile
- Exchange authorization code for token then you will get id_token

- Exchange authorization code for token then you will get id_token


-- Linkedin
- https://www.linkedin.com/developers
- Get client id and secret
- Hit below url to get code and use this code in request body for token field
- https://www.linkedin.com/oauth/v2/authorization?client_id=helloworld&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fhome&response_type=code&state=abcdef&scope=r_liteprofile%20r_emailaddress
- No playground has been found for linkedin

- Swagger
- http:https://localhost:8080/app/swagger-ui.html
Expand All @@ -35,6 +42,15 @@
}


- For Linkedin
- Request body
- {
"provider": "linkedin",
"token": " Get authorization code"
}



- For Apple :
- We need authorization code to validate on it.
- We are passing the values of firstName and lastName because when we get authorization code that time user-info will be provided after that only email will be received. This is current behaviour in APPLE doc.
Expand Down
16 changes: 13 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,15 @@
</dependency>

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
<version>2.9.2</version>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20210307</version>
</dependency>

<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.4.0</version>
</dependency>

<dependency>
Expand All @@ -75,6 +81,10 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
70 changes: 69 additions & 1 deletion src/main/java/com/sm/config/social/SocialClient.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
package com.sm.config.social;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.sm.common.error.type.ErrorType;
import com.sm.common.exception.GenericErrorException;
import com.sm.common.util.DateUtil;
import com.sm.common.util.SecureStringUtil;
import com.sm.config.social.ios.IOSClient;
import com.sm.config.social.user.IOSInfo;
import com.sm.config.social.user.FacebookUser;
import com.sm.config.social.user.GoogleUser;
import com.sm.config.social.user.IOSInfo;
import com.sm.config.social.user.LinkedinInfo;
import com.sm.controller.dto.request.SocialRequestModel;
import com.sm.dto.response.user.UserDto;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

Expand Down Expand Up @@ -113,6 +122,54 @@ public UserDto getAppleUser(SocialRequestModel socialRequestModel,String clientS
return userDto;
}


public UserDto getLinkedinInfo(String authorizationCode){
String redirectUrl = "http:https://localhost:8080/home";
String clientId = "abcdef";
String clientSecret = "helloworld";
//authorization code for access token
String accessTokenUri ="https://www.linkedin.com/oauth/v2/accessToken?grant_type=authorization_code&code="+authorizationCode+"&redirect_uri="+redirectUrl+"&client_id="+clientId+"&client_secret="+clientSecret+"";
String accessTokenRequest = restTemplate.getForObject(accessTokenUri, String.class);
JSONObject jsonObjOfAccessToken = new JSONObject(accessTokenRequest);
String accessToken = jsonObjOfAccessToken.get("access_token").toString();

//trade your access token
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Bearer " +accessToken);
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
// linkedin api to get linkedidn profile detail
String profileUri = "https://api.linkedin.com/v2/me";
ResponseEntity<String> linkedinDetailRequest = restTemplate.exchange(profileUri, HttpMethod.GET, entity, String.class);

LinkedinInfo linkedinInfo = null;
//response below for profile detail
//{"localizedLastName":"world","lastName":{"localized":{"en_US":"world"},"preferredLocale":{"country":"US","language":"en"}},"firstName":{"localized":{"en_US":"hello"},"preferredLocale":{"country":"US","language":"en"}},"id":"abcdef","localizedFirstName":"hello"}

try {
ObjectMapper objectMapper = new ObjectMapper();
linkedinInfo = objectMapper.readValue(linkedinDetailRequest.getBody(), LinkedinInfo.class);
} catch (Exception e) {
logger.error("While fetching linkedin data, getting Exception :",e);
throw new GenericErrorException(ErrorType.TOKEN_BAD_REQUEST.getCode(),ErrorType.TOKEN_BAD_REQUEST.getMessage(),e);
}

linkedinInfo = getLinkedinEmailInfo(entity, linkedinInfo);
return convertTo(linkedinInfo);

}

private LinkedinInfo getLinkedinEmailInfo(HttpEntity<String> entity, LinkedinInfo linkedinInfo) {
ResponseEntity<String> linkedinDetailRequest;
String emailUri = "https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))";
linkedinDetailRequest = restTemplate.exchange(emailUri, HttpMethod.GET, entity, String.class);

//{"elements":[{"handle":"urn:li:emailAddress:1000001","handle~":{"emailAddress":"[email protected]"}}]}
String ee = "$['elements'][0]['handle']['emailAddress']";
DocumentContext jsonContext = JsonPath.parse(linkedinDetailRequest.getBody());
linkedinInfo.setEmail(jsonContext.read("$['elements'][0]['handle~']['emailAddress']"));
return linkedinInfo;
}

private UserDto convertTo(FacebookUser facebookUser) {
UserDto userDto = new UserDto();
userDto.setProviderId(facebookUser.getId());
Expand Down Expand Up @@ -144,4 +201,15 @@ private UserDto convertTo(IOSInfo appleInfo) {
userDto.setPassword(SecureStringUtil.randomString(30));
return userDto;
}

private UserDto convertTo(LinkedinInfo linkedinInfo) {
UserDto userDto = new UserDto();
userDto.setProviderId(linkedinInfo.getId());
userDto.setProvider("linkedin");
userDto.setEmail(linkedinInfo.getEmail());
userDto.setFirstName(linkedinInfo.getLocalizedFirstName());
userDto.setLastName(linkedinInfo.getLocalizedLastName());
userDto.setPassword(SecureStringUtil.randomString(30));
return userDto;
}
}
46 changes: 46 additions & 0 deletions src/main/java/com/sm/config/social/user/LinkedinInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.sm.config.social.user;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class LinkedinInfo {
private String id;
private String localizedFirstName;
private String localizedLastName;
private String email;

public LinkedinInfo(){}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getLocalizedFirstName() {
return localizedFirstName;
}

public void setLocalizedFirstName(String localizedFirstName) {
this.localizedFirstName = localizedFirstName;
}

public String getLocalizedLastName() {
return localizedLastName;
}

public void setLocalizedLastName(String localizedLastName) {
this.localizedLastName = localizedLastName;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

}
22 changes: 22 additions & 0 deletions src/main/java/com/sm/controller/HomeController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.sm.controller;

import com.sm.common.exception.GenericErrorException;
import io.swagger.annotations.Api;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;


@RestController
@Api(value = "Home Resource")
public class HomeController {

private static final Logger LOGGER = LoggerFactory.getLogger(HomeController.class);

@PostMapping("/home")
public String getAuthorizationCode(@RequestParam("code") String authorizationCode) throws GenericErrorException {
return authorizationCode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class SocialRequestModel {

@NotBlank(message="NOT_BLANK")
@NotEmpty(message="NOT_BLANK")
@Pattern(regexp = "^(facebook|google|apple)$",flags = Pattern.Flag.CASE_INSENSITIVE, message = "PROVIDER_NOT_EMPTY")
@Pattern(regexp = "^(facebook|google|apple|linkedin)$",flags = Pattern.Flag.CASE_INSENSITIVE, message = "PROVIDER_NOT_EMPTY")
private String provider;

private String firstName;
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/sm/service/impl/UserServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ public UserDto validateAccessToken(SocialRequestModel socialRequestModel) throws
// implement above comments to set the value in clientSecret. Initially, it will be null
String clientSecret = null;
userDto = socialClient.getAppleUser(socialRequestModel, clientSecret);
} else if (provider.equalsIgnoreCase("linkedin")) {
userDto = socialClient.getLinkedinInfo(socialRequestModel.getToken());
}
UserDto userResponse = createUserSocial(userDto);
return userResponse;
Expand Down

0 comments on commit 68216bb

Please sign in to comment.