How to get access token from AuthenticationFlowContext on keycloak custom authenticator - java

I need to call one external API from the Keycloak custom authenticator authenticate(AuthenticationFlowContext context) method, for that, I need keycloak access token.
How to get the access token from the AuthenticationFlowContext.
Authenticator class:
public class CMAuthenticator implements Authenticator
{
#Override
public void authenticate(AuthenticationFlowContext context)
{
try
{
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
final String userName = formData.getFirst("username");
final String pwd = formData.getFirst("password");
String cmLoginURL = getCMAuthenticatorConfig(context);
String loginObj = "{\"username\": \"" + userName + "\", \"password\":\"" + pwd + "\"}";
Entity<String> entity = Entity.text(loginObj);
ResteasyClient client = new ResteasyClientBuilder().build();
ResteasyWebTarget target = client.target(cmLoginURL);
Response response = target.request(MediaType.TEXT_PLAIN).post(entity);
if (response.getStatus() != 200)
{
context.getEvent().user(context.getUser());
context.getEvent().error(Errors.ACCESS_DENIED);
context.failure(AuthenticationFlowError.INVALID_USER);
return;
}
}
catch (Exception e)
{
context.getEvent().user(context.getUser());
context.getEvent().error(Errors.ACCESS_DENIED);
context.failure(AuthenticationFlowError.INVALID_USER);
return;
}
context.success();
}
}

Related

Sendgrid throwing error The from object must be provided for every email send

{"personalizations":[{"to":[{"email":"<EMAIL>"}],"from":{"name":"ABCD","email":"<EMAIL>"},"subject":"Verify OTP","custom_args":{"OTP":"dsgsdf"}}],"template_id":"<TEMPLATE_ID>"}
{{"errors":[{"message":"The from object must be provided for every email send. It is an object that requires the email parameter, but may also contain a name parameter. e.g. {"email" : "example#example.com"} or {"email" : "example#example.com", "name" : "Example Recipient"}.","field":"from.email","help":"http://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/errors.html#message.from"}]}
public void sendEmail(String otp, String email, String toName) {
Email from = new Email();
from.setEmail(sendgridFrom);
from.setName(fromName);
String subject = "Verify OTP";
Email to = new Email();
to.setName(toName);
to.setEmail(email);
DynamicTemplatePersonalization personalization = new DynamicTemplatePersonalization();
personalization.addTo(to);
Mail mail = new Mail();
mail.setFrom(from);
personalization.setSubject(subject);
personalization.addDynamicTemplateData("OTP", otp);
mail.addPersonalization(personalization);
mail.setTemplateId(sendgridTemplate);
SendGrid sg = new SendGrid(sendgridApiKey);
Request request = new Request();
try {
request.setMethod(Method.POST);
request.setEndpoint("mail/send");
request.setBody(mail.build());
Response response = sg.api(request);
int currentIndexCount = 0;
int status = response.getStatusCode();
while (status != 202 && currentIndexCount < maxEmailRetries) {
response = sg.api(request);
status = response.getStatusCode();
currentIndexCount++;
}
log.debug(subject, response.getStatusCode());
} catch (IOException ex) {
ex.printStackTrace();
}
}
private static class DynamicTemplatePersonalization extends Personalization {
#JsonProperty(value = "dynamic_template_data")
private Map<String, Object> dynamic_template_data;
#JsonProperty("dynamic_template_data")
public Map<String, Object> getDynamicTemplateData() {
if (dynamic_template_data == null) {
return Collections.<String, Object>emptyMap();
}
return dynamic_template_data;
}
public void addDynamicTemplateData(String key, String value) {
if (dynamic_template_data == null) {
dynamic_template_data = new HashMap<String, Object>();
dynamic_template_data.put(key, value);
} else {
dynamic_template_data.put(key, value);
}
}
}
This code worked for me.

How I can test that an OkHttpCall is performed with specific headers?

I have the following class:
class MyClass {
private OkHttpClient httpClient;
private String session_id;
public MyClass() {
this.setHttpClient(new OkHttpClient());
}
public String getSessionId() {
return session_id;
}
public void setHttpClient(OkHttpClient httpClient) {
this.htttpClient = httpClient;
}
public String retrieveUrlContents(String url, String csrfToken) throws Exception {
url = this.url.replaceAll("/$", "") + "/" + url.replaceAll("^/", "");
csrfToken = (csrfToken == null) ? "" : csrfToken;
if (!csrfToken.equals("")) {
long unixtime = System.currentTimeMillis() / 1000L;
// AJAX Calls also require to offer the _ with a unix timestamp alongside csrf token
url += "?_=" + unixtime + "&csrf_token=" + csrfToken;
}
Request.Builder request = new Request.Builder()
.url(url)
.header("User-Agent", "Mozila/5.0 (X11;Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0");
String session_id = this.getSessionId();
session_id = session_id == null ? "" : session_id;
if (!session_id.equals("")) {
request.header("Set-Cookie", "session_id=" + session_id + ";login_uid=" + Math.random());
}
Response response = this.httpClient.newCall(request.build()).execute();
int code = response.code();
if (code != 200) {
throw new Exception("The url " + url + " returned code " + code);
}
String responseBody = response.body().string();
return responseBody;
}
}
And I want to unit-test the case that if getSessionId actually return a non-null or a non-empty string then the httpCall is performed:
class MyClassTest {
private static OkHttpClient mockHttpClient(final String serializedBody, final boolean json, int code) throws IOException {
final OkHttpClient okHttpClient = mock(OkHttpClient.class);
final Call remoteCall = mock(Call.class);
code = code < 0 ? 200 : code;
final Response response = new Response.Builder()
.request(new Request.Builder().url("http://url.com").build())
.protocol(Protocol.HTTP_1_1)
.code(code).message("").body(
ResponseBody.create(
MediaType.parse(json ? "application/json" : "text/html"),
serializedBody
))
.build();
when(remoteCall.execute()).thenReturn(response);
when(okHttpClient.newCall(any())).thenReturn(remoteCall);
return okHttpClient;
}
#Test
public void retrieveUrlContentsIsRetrievedWithSessionId() {
File file = (new File("src/test/resources/csrfInvalid.html")).getAbsoluteFile();
String path = file.getPath();
Scanner fileReader = new Scanner(file);
String contents = fileReader.useDelimiter("\\Z").next();
OkHttpClient client = this.mockHttpClient(contents, false, 200);
final Η300sCredentialsRetriever retriever = spy(Η300sCredentialsRetriever.class);
doReturn("Hello").when(retriever).getSessionId();
retriever.setUrl("192.168.2.1");
retriever.setHttpClient(client);
String response = retriever.retrieveUrlContents("/example.html");
// Test that http call is permormed with SessionId
// Rest of Assertions
}
}
What I want is to Assert that OkHttp3 is performing an HttpCall with the appropriate Cookie Header. But I do not know how I can assert that the HttpCall is performed with this header. Do you have any ideas how I can test that?
One option is MockWebServer, look at RecordedRequest which can confirm the headers you sent.
https://github.com/square/okhttp/tree/master/mockwebserver
https://www.baeldung.com/spring-mocking-webclient#mockwebserverchecking
RecordedRequest request1 = server.takeRequest();
assertEquals("/v1/chat/messages/", request1.getPath());
assertNotNull(request1.getHeader("Authorization"));

Verify OAuth1a signed request using Twitter joauth with RSA-SHA1?

I have a use case to authenticate OAuth1 request which is signed using RSA Private Key and verified at server end with RSA public key.
I found this library from Twitter which helps us authenticate/verify the Oauth signed requests. https://github.com/twitter/joauth
I want to leverage this library for verifying the request from Jersey or Spring MVC action method. The request from client would have been signed using private key. At my end I would use the public key of the client to verify the request. which means RSA-SHA1 algo.
Twitter joauth seem to be useful but I am missing the code that would transform HttpServletRequest to OAuthRequest
The library read-me file suggests this as facility but I could not find a code that does javax.servlet.http.HttpServletRequest --> com.twitter.joauth.OAuthRequest transformation.
The request verification happens in verify method which has following signature.
public VerifierResult verify(UnpackedRequest.OAuth1Request request, String tokenSecret, String consumerSecret);
Secondly I also want to know which is the most appropriate way to use/read RSA public key with twitter joauth when verify method takes String parameter ?
I have never used any library to authenticate users via Twitter. But I have just looked in the UnpackedRequest.OAuth1Request. You can create an instance of this class by filling all parameters. I have written Twitter OAuth Header creator, so you can just use it to fill those parameters or send POST requests directly without a library.
Here all classes what you need:
Signature - to generate an OAuth Signature.
public class Signature {
private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
public static String calculateRFC2104HMAC(String data, String key)
throws java.security.SignatureException
{
String result;
try {
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(data.getBytes());
result = new String(Base64.encodeBase64(rawHmac));
} catch (Exception e) {
throw new SignatureException("Failed to generate HMAC : " + e.getMessage());
}
return result;
}
}
NvpComparator - to sort parameters you need in the header.
public class NvpComparator implements Comparator<NameValuePair> {
#Override
public int compare(NameValuePair arg0, NameValuePair arg1) {
String name0 = arg0.getName();
String name1 = arg1.getName();
return name0.compareTo(name1);
}
}
OAuth - for URL encode.
class OAuth{
...
public static String percentEncode(String s) {
return URLEncoder.encode(s, "UTF-8")
.replace("+", "%20").replace("*", "%2A")
.replace("%7E", "~");
}
...
}
HeaderCreator - to create all needed parameters and generate an OAuth header param.
public class HeaderCreator {
private String authorization = "OAuth ";
private String oAuthSignature;
private String oAuthNonce;
private String oAuthTimestamp;
private String oAuthConsumerSecret;
private String oAuthTokenSecret;
public String getAuthorization() {
return authorization;
}
public String getoAuthSignature() {
return oAuthSignature;
}
public String getoAuthNonce() {
return oAuthNonce;
}
public String getoAuthTimestamp() {
return oAuthTimestamp;
}
public HeaderCreator(){}
public HeaderCreator(String oAuthConsumerSecret){
this.oAuthConsumerSecret = oAuthConsumerSecret;
}
public HeaderCreator(String oAuthConsumerSecret, String oAuthTokenSecret){
this(oAuthConsumerSecret);
this.oAuthTokenSecret = oAuthTokenSecret;
}
public String getTwitterServerTime() throws IOException, ParseException {
HttpsURLConnection con = (HttpsURLConnection)
new URL("https://api.twitter.com/oauth/request_token").openConnection();
con.setRequestMethod("HEAD");
con.getResponseCode();
String twitterDate= con.getHeaderField("Date");
DateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
Date date = formatter.parse(twitterDate);
return String.valueOf(date.getTime() / 1000L);
}
public String generatedSignature(String url, String method, List<NameValuePair> allParams,
boolean withToken) throws SignatureException {
oAuthNonce = String.valueOf(System.currentTimeMillis());
allParams.add(new BasicNameValuePair("oauth_nonce", oAuthNonce));
try {
oAuthTimestamp = getTwitterServerTime();
allParams.add(new BasicNameValuePair("oauth_timestamp", oAuthTimestamp));
}catch (Exception ex){
//TODO: Log!!
}
Collections.sort(allParams, new NvpComparator());
StringBuffer params = new StringBuffer();
for(int i=0;i<allParams.size();i++)
{
NameValuePair nvp = allParams.get(i);
if (i>0) {
params.append("&");
}
params.append(nvp.getName() + "=" + OAuth.percentEncode(nvp.getValue()));
}
String signatureBaseStringTemplate = "%s&%s&%s";
String signatureBaseString = String.format(signatureBaseStringTemplate,
OAuth.percentEncode(method),
OAuth.percentEncode(url),
OAuth.percentEncode(params.toString()));
String compositeKey = OAuth.percentEncode(oAuthConsumerSecret)+"&";
if(withToken) compositeKey+=OAuth.percentEncode(oAuthTokenSecret);
oAuthSignature = Signature.calculateRFC2104HMAC(signatureBaseString, compositeKey);
return oAuthSignature;
}
public String generatedAuthorization(List<NameValuePair> allParams){
authorization = "OAuth ";
Collections.sort(allParams, new NvpComparator());
for(NameValuePair nvm : allParams){
authorization+=nvm.getName()+"="+OAuth.percentEncode(nvm.getValue())+", ";
}
authorization=authorization.substring(0,authorization.length()-2);
return authorization;
}
}
Explain:
1. getTwitterServerTime
In oAuthTimestamp you need not your time of server but the time of a Twitter server. You can optimize it saving this param if you always send requests in the certain Twitter server.
2. HeaderCreator.generatedSignature(...)
url - logically url to twitter API
method - GET or POST. You must use always "POST"
allParams - Parameters which you know to generate signature ("param_name", "param_value");
withToken - if you know oAuthTokenSecret put true. Otherwise false.
3. HeaderCreator.generatedAuthorization(...)
Use this method after generatedSignature(...) to generate an OAuth header string.
allParams - it is parameters which you have used in generatedSignature(...) plus: nonce, signature, timestamp. Always use:
allParams.add(new BasicNameValuePair("oauth_nonce", headerCreator.getoAuthNonce()));
allParams.add(new BasicNameValuePair("oauth_signature", headerCreator.getoAuthSignature()));
allParams.add(new BasicNameValuePair("oauth_timestamp", headerCreator.getoAuthTimestamp()));
Now you can use it to fill UnpackedRequest.OAuth1Request in your library. Also here an example to authenticate user in SpringMVC without the library:
Requests - to send post requests.
public class Requests {
public static String sendPost(String url, String urlParameters, Map<String, String> prop) throws Exception {
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
con.setRequestMethod("POST");
if(prop!=null) {
for (Map.Entry<String, String> entry : prop.entrySet()) {
con.setRequestProperty(entry.getKey(), entry.getValue());
}
}
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
BufferedReader in;
if(responseCode==200) {
in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
}else{
in = new BufferedReader(
new InputStreamReader(con.getErrorStream()));
}
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
}
}
twAuth(...) - put it in your controller. Execute it when an user want to authenticate in your site via Twitter.
#RequestMapping(value = "/twauth", method = RequestMethod.GET)
#ResponseBody
public String twAuth(HttpServletResponse response) throws Exception{
try {
String url = "https://api.twitter.com/oauth/request_token";
List<NameValuePair> allParams = new ArrayList<NameValuePair>();
allParams.add(new BasicNameValuePair("oauth_callback", "http://127.0.0.1:8080/twlogin"));
allParams.add(new BasicNameValuePair("oauth_consumer_key", "2YhNLyum1VY10UrWBMqBnatiT"));
allParams.add(new BasicNameValuePair("oauth_signature_method", "HMAC-SHA1"));
allParams.add(new BasicNameValuePair("oauth_version", "1.0"));
HeaderCreator headerCreator = new HeaderCreator("RUesRE56vVWzN9VFcfA0jCBz9VkvkAmidXj8d1h2tS5EZDipSL");
headerCreator.generatedSignature(url,"POST",allParams,false);
allParams.add(new BasicNameValuePair("oauth_nonce", headerCreator.getoAuthNonce()));
allParams.add(new BasicNameValuePair("oauth_signature", headerCreator.getoAuthSignature()));
allParams.add(new BasicNameValuePair("oauth_timestamp", headerCreator.getoAuthTimestamp()));
Map<String, String> props = new HashMap<String, String>();
props.put("Authorization", headerCreator.generatedAuthorization(allParams));
String twitterResponse = Requests.sendPost(url,"",props);
Integer indOAuthToken = twitterResponse.indexOf("oauth_token");
String oAuthToken = twitterResponse.substring(indOAuthToken, twitterResponse.indexOf("&",indOAuthToken));
response.sendRedirect("https://api.twitter.com/oauth/authenticate?" + oAuthToken);
}catch (Exception ex){
//TODO: Log
throw new Exception();
}
return "main";
}
twLogin(...) - put it in your controller. It is callback from Twitter.
#RequestMapping(value = "/twlogin", method = RequestMethod.GET)
public String twLogin(#RequestParam("oauth_token") String oauthToken,
#RequestParam("oauth_verifier") String oauthVerifier,
Model model, HttpServletRequest request){
try {
if(oauthToken==null || oauthToken.equals("") ||
oauthVerifier==null || oauthVerifier.equals(""))
return "main";
String url = "https://api.twitter.com/oauth/access_token";
List<NameValuePair> allParams = new ArrayList<NameValuePair>();
allParams.add(new BasicNameValuePair("oauth_consumer_key", "2YhNLyum1VY10UrWBMqBnatiT"));
allParams.add(new BasicNameValuePair("oauth_signature_method", "HMAC-SHA1"));
allParams.add(new BasicNameValuePair("oauth_token", oauthToken));
allParams.add(new BasicNameValuePair("oauth_version", "1.0"));
NameValuePair oAuthVerifier = new BasicNameValuePair("oauth_verifier", oauthVerifier);
allParams.add(oAuthVerifier);
HeaderCreator headerCreator = new HeaderCreator("RUesRE56vVWzN9VFcfA0jCBz9VkvkAmidXj8d1h2tS5EZDipSL");
headerCreator.generatedSignature(url,"POST",allParams,false);
allParams.add(new BasicNameValuePair("oauth_nonce", headerCreator.getoAuthNonce()));
allParams.add(new BasicNameValuePair("oauth_signature", headerCreator.getoAuthSignature()));
allParams.add(new BasicNameValuePair("oauth_timestamp", headerCreator.getoAuthTimestamp()));
allParams.remove(oAuthVerifier);
Map<String, String> props = new HashMap<String, String>();
props.put("Authorization", headerCreator.generatedAuthorization(allParams));
String twitterResponse = Requests.sendPost(url,"oauth_verifier="+oauthVerifier,props);
//Get user id
Integer startIndexTmp = twitterResponse.indexOf("user_id")+8;
Integer endIndexTmp = twitterResponse.indexOf("&",startIndexTmp);
if(endIndexTmp<=0) endIndexTmp = twitterResponse.length()-1;
Long userId = Long.parseLong(twitterResponse.substring(startIndexTmp, endIndexTmp));
//Do what do you want...
}catch (Exception ex){
//TODO: Log
throw new Exception();
}
}

access LTPA token outside of WebSphere context

I've a web app which is deployed in tomcat and from this web app, i have to consume a SOAP service which is deployed in Websphere. To access this service, i need to pass LTPA token. I'm very new to websphere, don't know how can i get LTPA token in my web app ? I can't modify the implementation of the app which is deployed in web sphere.
I could acheive this by using HttpBasicAuthentication. Here is the code snippet -
public class TokenHelper {
private static Logger logger = LoggerFactory.getLogger(TokenHelper.class);
private static final int HTTP_TIMEOUT_MILISEC = 100000;
private static String lineSeparator = System.getProperty("line.separator");
#Value("#{'${hostname}'}")
private String hostName;
#Value("#{'${port}'}")
private int port;
#Value("#{'${contextpath}'}")
private String contextPath;
#Value("#{'${isbasicauthentication}'}")
private boolean isBasicAuthentication;
#Value("#{'${username}'}")
private String basicAuthenticationUserName;
#Value("#{'${userpassword}'}")
private String basicAuthenticationPassword;
public Map<String, String> getLtpaToken() throws Exception {
Cookie[] cookies = null;
Protocol protocol = null;
Map<String, String> cookiesMap = new HashMap<String, String>();
GetMethod method = new GetMethod();
HttpClient client = new HttpClient();
method.getParams().setSoTimeout(HTTP_TIMEOUT_MILISEC);
protocol = new Protocol("http", new DefaultProtocolSocketFactory(), getPort());
if (isBasicAuthentication) {
client.getParams().setAuthenticationPreemptive(true);
Credentials defaultcreds = new UsernamePasswordCredentials(getBasicAuthenticationUserName(), getBasicAuthenticationPassword());
client.getState().setCredentials(new AuthScope(getHostName(), getPort(), AuthScope.ANY_REALM), defaultcreds);
}
// Execute request
try {
client.getHostConfiguration().setHost(getHostName(), getPort(), protocol);
method = new GetMethod(getContextPath());
method.setFollowRedirects(true);
logger.info(methodName, "URL to get:" + getContextPath());
// Execute the GET method
int statusCode = client.executeMethod(method);
if (statusCode != -1) {
cookies = client.getState().getCookies();
StringBuffer sb = new StringBuffer();
for (int j = 0; j < cookies.length; j++) {
cookiesMap.put(cookies[j].getName(), cookies[j].getValue());
sb.append("CookieName=" + cookies[j].getName() + lineSeparator);
sb.append("Value=" + cookies[j].getValue() + lineSeparator);
sb.append("Domain=" + cookies[j].getDomain() + lineSeparator);
}
sb.append("Status Text>>>" + HttpStatus.getStatusText(statusCode));
logger.debug("Cookies are: {}" + sb.toString());
method.releaseConnection();
}
} catch (Exception e) {
logger.error("Error while getting LTPA token using HttpBasicAuthentication for URL {}" +e);
throw new RuntimeException("Error while getting LTPA token using HttpBasicAuthentication for URL:" + contextPath, e);
} finally {
// Release current connection to the connection pool once you
// are done
method.releaseConnection();
}
return cookiesMap;
}

LinkedIn integration - Establish a requestToken

I'm developing (trying for now) portlet that will be integrated with LinkedIn.
Following the documentation about it:
http://developer.linkedin.com/docs/DOC-1008 -->
The first step to authorizing a LinkedIn member is requesting a requestToken. This request is done with an HTTP POST.
For the requestToken step, the following components should be present in your string to sign:
* HTTP Method (POST)
* Request URI (https://api.linkedin.com/uas/oauth/requestToken)
* oauth_callback
* oauth_consumer_key
* oauth_nonce
* oauth_signature_method
* oauth_timestamp
* oauth_version
I have already API(it's oauth_consumer_key) key and i need to generate specific URL string.
Have next java code for this URL and HTTP connection:
private void processAuthentication() {
Calendar cal = Calendar.getInstance();
Long ms = cal.getTimeInMillis();
Long timestamp = ms / 1000;
Random r = new Random();
Long nonce = r.nextLong();
String prefixUrl = "https://api.linkedin.com/uas/oauth/requestToken";
String oauthCallback = "oauth_callback=http://localhost/";
String oauthConsumerKey =
"&oauth_consumer_key=my_consumer_key";
String oauthNonce = "&oauth_nonce=" + nonce.toString();
String oauthSignatureMethod = "&oauth_signature_method=HMAC-SHA1";
String oauthTimestamp = "&oauth_timestamp=" + timestamp.toString();
String oauthVersion = "&oauth_version=1.0";
String mainUrl =
oauthCallback + oauthConsumerKey + oauthNonce + oauthSignatureMethod
+ oauthTimestamp + oauthVersion;
try {
prefixUrl =
URLEncoder.encode(prefixUrl, "UTF-8") + "&"
+ URLEncoder.encode(mainUrl, "UTF-8");
URL url = new URL(prefixUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
String msg = connection.getResponseMessage();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
The question is next,for those, who had faced this problem:
How should really look URL string for connection and how response is received?
For URL, it's interested the example of URL, you generated.
And for response interested, method to get it.
As i understand, after HTTP connection been established,that response is:
connection.getResponseMessage();
#sergionni I found answer to your Question from linkedin-developer
As you know
The first step to authorizing a Linked-In member is requesting a requestToken. This request is done with an HTTP POST.
Your base string should end up looking something like this if you're using a callback:
POST&https%3A%2F%2Fapi.linkedin.com%2Fuas%2Foauth%2FrequestToken
&oauth_callback%3Dhttp%253A%252F%252Flocalhost%252Foauth_callback%26o
auth_consumer_key%3DABCDEFGHIJKLMNOPQRSTUVWXYZ%26
oauth_nonce%3DoqwgSYFUD87MHmJJDv7bQqOF2EPnVus7Wkqj5duNByU%26
oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1259178158%26
oauth_version%3D1.0
You then sign this base string with your consumer_secret, computing a signature. In this case, if your secret was 1234567890, the signature would be TLQXuUzM7omwDbtXimn6bLDvfF8=.
Now you take the signature you generated, along with oauth_nonce, oauth_callback, oauth_signature_method, oauth_timestamp, oauth_consumer_key, and oauth_version and create an HTTP Authorization header. For this request, that HTTP header would look like:
Authorization: OAuth
oauth_nonce="oqwgSYFUD87MHmJJDv7bQqOF2EPnVus7Wkqj5duNByU",
oauth_callback="http%3A%2F%2Flocalhost%2Foauth_callback",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1259178158",
oauth_consumer_key="ABCDEFGHIJKLMNOPQRSTUVWXYZ",
oauth_signature="TLQXuUzM7omwDbtXimn6bLDvfF8=",
oauth_version="1.0"
Please note, that the HTTP header is a single header -- not an HTTP header for each component. You can optionally supply a realm="http://api.linkedin.com".
As a response to your request for a requestToken, your requestToken will be in the "oauth_token" response field, a validation that we acknowledged your callback with the "oauth_callback_confirmed" field, an oauth_token_secret, and a oauth_expires_in, and a few other values.
(here us Your answaer) response would look like:
oauth_token=94ab03c4-ae2c-45e4-8732-0e6c4899db63
&oauth_token_secret=be6ccb24-bf0a-4ea8-a4b1-0a70508e452b
&oauth_callback_confirmed=true&oauth_expires_in=599
You might try out the OAuth libraries to handle the connection: http://code.google.com/p/oauth/
I created a plugin for Play Framework to easily integrated with LinkedIn's OAuth: geeks.aretotally.in/projects/play-framework-linkedin-module. Hopefully it can help. You should def check out Play, very very cool Java framework.
portlet body:
public class LinkedInPortlet extends GenericPortlet {
public static final String PAGE_PIN = "pin";
public static final String PAGE_EDIT = "edit";
public static final String PAGE_PROFILE = "profile";
public static final String PAGE_CONNECTIONS = "connections";
public static final String FORM_LINKEDIN_PREFERENCES = "preferencesLinkedInForm";
public static final String PAGE_VIEW_MY_PROFILE = "/WEB-INF/portlets/linkedin/myProfile.jsp";
public static final String PAGE_VIEW_MY_CONNECTIONS =
"/WEB-INF/portlets/linkedin/myConnections.jsp";
public static final String PAGE_PREFERENCES = "/WEB-INF/portlets/linkedin/edit.jsp";
public void doView(RenderRequest request, RenderResponse response) throws PortletException,
IOException {
String view = PAGE_VIEW_MY_PROFILE;
String page =
(String) request.getPortletSession().getAttribute(
"page_" + getPortletIdentifier(request), PortletSession.PORTLET_SCOPE);
String accessTokenToken =
getStringConfiguration(request, LinkedInPreferencesForm.PARAM_ACCESS_TOKEN_TOKEN);
String accessTokenSecret =
getStringConfiguration(request, LinkedInPreferencesForm.PARAM_ACCESS_TOKEN_SECRET);
LinkedInContact profile = new LinkedInContact();
List<LinkedInContact> contacts = new ArrayList<LinkedInContact>();
if (PAGE_PIN.equals(page)) {
view = PAGE_PREFERENCES;
} else if (PAGE_EDIT.equals(page)) {
view = PAGE_PREFERENCES;
} else if (PAGE_CONNECTIONS.equals(page)) {
try {
contacts =
ServiceResolver.getResolver().getLinkedInService().getConnections(
accessTokenToken, accessTokenSecret);
} catch (ServiceException se) {
view = PAGE_PREFERENCES;
handleException(request, se);
}
view = PAGE_VIEW_MY_CONNECTIONS;
} else {
try {
profile =
ServiceResolver.getResolver().getLinkedInService().getProfile(
accessTokenToken, accessTokenSecret);
} catch (ServiceException se) {
view = PAGE_PREFERENCES;
handleException(request, se);
}
view = PAGE_VIEW_MY_PROFILE;
}
request.setAttribute("profile", profile);
request.setAttribute("contacts", contacts);
response.setContentType(request.getResponseContentType());
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(view);
rd.include(request, response);
}
public void processAction(ActionRequest request, ActionResponse response)
throws PortletException, IOException {
String action;
action = (String) request.getParameter("action");
String page = request.getParameter("page");
if (page == null) {
page = PAGE_PROFILE;
} else if ("auth".equals(action)) {
request.getPortletSession().setAttribute(
"requestToken_" + getPortletIdentifier(request),
ServiceResolver.getResolver().getLinkedInService().getRequestToken(),
PortletSession.APPLICATION_SCOPE);
LinkedInPreferencesForm form = new LinkedInPreferencesForm(request);
request.getPortletSession().setAttribute(
FORM_LINKEDIN_PREFERENCES + getPortletIdentifier(request), form,
PortletSession.APPLICATION_SCOPE);
response.setPortletMode(PortletMode.EDIT);
} else if ("save".equals(action)) {
try {
try {
savePreferences(request, response);
} catch (ServiceException e) {
handleException(request, e);
}
} catch (PortletModeException e) {
handleException(request, e);
}
} else if ("myProfile".equals(action)) {
page = PAGE_PROFILE;
} else if ("myConnections".equals(action)) {
page = PAGE_CONNECTIONS;
}
if (page != null) {
request.getPortletSession().setAttribute("page_" + getPortletIdentifier(request), page,
PortletSession.PORTLET_SCOPE);
}
}
private void savePreferences(ActionRequest request, ActionResponse response)
throws PortletModeException, ServiceException {
LinkedInPreferencesForm form = new LinkedInPreferencesForm(request);
if (validateForm(request, form)) {
LinkedInRequestToken requestToken =
(LinkedInRequestToken) request.getPortletSession().getAttribute(
"requestToken_" + getPortletIdentifier(request),
PortletSession.APPLICATION_SCOPE);
String pin = request.getParameter("pinCode");
LinkedInAccessToken accessToken;
try {
accessToken =
ServiceResolver.getResolver().getLinkedInService().getAccessToken(
requestToken, pin);
} catch (LinkedInOAuthServiceException ase) {
response.setPortletMode(PortletMode.EDIT);
throw new ServiceException("linkedin.authentication.failed");
}
String tokenToken = requestToken.getToken();
String secret = requestToken.getTokenSecret();
String tokenURL = requestToken.getAuthorizationUrl();
Properties configuration = new Properties();
configuration.setProperty(LinkedInPreferencesForm.PARAM_PIN, form.getPin());
configuration
.setProperty(LinkedInPreferencesForm.PARAM_REQUEST_TOKEN_TOKEN, tokenToken);
configuration.setProperty(LinkedInPreferencesForm.PARAM_REQUEST_TOKEN_SECRET, secret);
configuration.setProperty(LinkedInPreferencesForm.PARAM_REQUEST_TOKEN_URL, tokenURL);
configuration.setProperty(LinkedInPreferencesForm.PARAM_ACCESS_TOKEN_TOKEN, accessToken
.getToken());
configuration.setProperty(LinkedInPreferencesForm.PARAM_ACCESS_TOKEN_SECRET,
accessToken.getTokenSecret());
ServiceResolver.getResolver().getPortalService().savePortletConfiguration(request,
configuration);
resetSessionForm(request, FORM_LINKEDIN_PREFERENCES);
response.setPortletMode(PortletMode.VIEW);
} else {
// store in session
request.getPortletSession().setAttribute(
FORM_LINKEDIN_PREFERENCES + getPortletIdentifier(request), form,
PortletSession.APPLICATION_SCOPE);
response.setPortletMode(PortletMode.EDIT);
logger.debug(FORM_LINKEDIN_PREFERENCES + " is in edit mode");
}
}
#Override
protected void addConfiguration(MessageSource messageSource, Locale locale,
Map<String, String> result) {
result.put(LinkedInPreferencesForm.PARAM_PIN, messageSource.getMessage(
"linkedIn.preferences.pin", null, locale));
result.put(LinkedInPreferencesForm.PARAM_REQUEST_TOKEN_TOKEN, messageSource.getMessage(
"linkedIn.preferences.requestTokenToken", null, locale));
result.put(LinkedInPreferencesForm.PARAM_REQUEST_TOKEN_SECRET, messageSource.getMessage(
"linkedIn.preferences.requestTokenSecret", null, locale));
result.put(LinkedInPreferencesForm.PARAM_REQUEST_TOKEN_URL, messageSource.getMessage(
"linkedIn.preferences.requestTokenURL", null, locale));
result.put(LinkedInPreferencesForm.PARAM_ACCESS_TOKEN_TOKEN, messageSource.getMessage(
"linkedIn.preferences.accessToken", null, locale));
result.put(LinkedInPreferencesForm.PARAM_ACCESS_TOKEN_SECRET, messageSource.getMessage(
"linkedIn.preferences.accessTokenSecret", null, locale));
}
#Override
protected void addPreference(MessageSource messageSource, Locale locale,
Map<String, String> result) {
}
#Override
public String getAsyncTitle(RenderRequest request) {
return this.getTitle(request);
}
protected boolean validateForm(ActionRequest request, LinkedInPreferencesForm form) {
return form.validate();
}
protected String myEdit(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
LinkedInPreferencesForm form = new LinkedInPreferencesForm();
form.setPin(getStringConfiguration(request, LinkedInPreferencesForm.PARAM_PIN));
form.setRequestTokenToken(getStringConfiguration(request,
LinkedInPreferencesForm.PARAM_REQUEST_TOKEN_TOKEN));
form.setRequestTokenSecret(getStringConfiguration(request,
LinkedInPreferencesForm.PARAM_REQUEST_TOKEN_SECRET));
form.setRequestTokenURL(getStringConfiguration(request,
LinkedInPreferencesForm.PARAM_REQUEST_TOKEN_URL));
registerSessionForm(request, FORM_LINKEDIN_PREFERENCES, form);
LinkedInRequestToken requestToken;
requestToken =
(LinkedInRequestToken) request.getPortletSession().getAttribute(
"requestToken_" + getPortletIdentifier(request),
PortletSession.APPLICATION_SCOPE);
if (requestToken == null) {
requestToken =
new LinkedInRequestToken(form.getRequestTokenToken(), form
.getRequestTokenSecret());
requestToken.setAuthorizationUrl(form.getRequestTokenURL());
}
request.setAttribute("requestToken", requestToken);
return PAGE_PREFERENCES;
}
}

Categories