Trying to get an access token using restFB. but not directing - facebook

Hello i'm playing with spring boot and learning web services. I started playing with facebook graph api and using restfb. I get the access token and hard code it every time. Now i dont always want to hard code my credentials(access tokens), i want to be able to get the token when i sign in into my account without hard coding the access tokens every time i try to retrieve my photos from face and use it in my application. Has anyone worked with restfb show me an example of how to automatically get the access tokens without hard coding it. Thanks. My uri is just "localhost:8080/myapp."
#Controller
#RequestMapping("/")
public class HomeController {
#Value("#{faceBookappId['APP_KEY']}")
private static String APP_KEY;
#Value("#{faceBookappSecret['SECRET']}")
private static String APP_SECRET;
private FacebookClient.AccessToken getFaceBookUserToken(String code, String url) throws IOException {
WebRequestor web = new DefaultWebRequestor();
WebRequestor.Response accessTokens = web.executeGet("https://graph.facebook.com/oauth/access_token?client_id="+
APP_KEY+url+"&client_secret="+APP_SECRET+"&code=" + code);
return DefaultFacebookClient.AccessToken.fromQueryString(accessTokens.getBody());
}
#RequestMapping(method= RequestMethod.GET)
public String helloFaceBook(Model model) {
String url = "https://www.facebook.com/dialog/oauth?"+APP_KEY;
return "redirect"+url;
}
}

You can use the obtainUserAccessToken from the DefaultFacebookClient
FacebookClient facebookClient = new DefaultFacebookClient(Version.VERSION_2_2);
facebookClient.obtainUserAccessToken(appId, appSecret, redirectUri, verificationCode);

Related

IdentityServer - pass extra params from endsession endpoint to Logout

How we can pass extra params (which we send as query params to endsession endpoint) to Logout when user is not authenticated in IDP SSO
I'm using latest Identity Server 4.
In the standard case, when client initiates a logout (by accessing endsession endpoint), everything works fine when we have information about the user (which is stored in a cookie and endsession endpoint can successfully read that). EndSession redirects to https://myidp/Account/Logout?logoutId=someId and we can get any parameter which was passed in query string to endsession endpoint
But when we try to do second logout from the client (and there is no authenticated user in cookie), logoutId parameter is not passed to Logout endpoint and there is no chance to get params which we sent in query string to endsession endpoint
The reason why we need this is simple:
suppose client clicked logout twice on 2 different pages (client's pages)
when user was logged out, we want to redirect it back to client URL OR to add some extra logic depending on params which we send to endsession endpoint. But as we don't get any params in Logout method - we don't know anything about the client and what to do with this logout request
For now as workaround of this problem I added middleware in .Net Core app, which validates LogoutId parameter. If it doesn't exist (the case when we will not be able to get initial parameters, as no logoutId was passed in the query string to logout method), I add manually query string parameters from my middleware to the redirected URL
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
namespace IdentityProviderWebApp.Core
{
public class EndRequestMiddleware
{
private readonly RequestDelegate _next;
public EndRequestMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
await _next(context);
if (context.Request.Path.Value == "/connect/endsession")
{
var logoutUrl = context.Response.Headers["location"].ToString();
if (!logoutUrl.Contains("?"))
{
var fixedLocation = context.Response.Headers["location"] + context.Request.QueryString;
context.Response.Headers.Remove("location");
context.Response.Headers.Add("location", new StringValues(fixedLocation));
}
}
}
}
}
Register middleware code
app.UseMiddleware<EndRequestMiddleware>();
In AccountController Logout method get your expected variables as parameters of logout method
public async Task<IActionResult> Logout(string logoutId, string client_id, string redirect_uri)
In the Logout method get actual variable either from a valid context (if LogoutId exists) or use value which you receive in your Logout method
var logout = await _interaction.GetLogoutContextAsync(logoutId);
clientId = logout.Parameters.Get("client_id") ?? clientId;
redirectUri = logout.Parameters.Get("redirect_uri") ?? redirectUri;
Hope someone will find better approach

How to authenticate and redirect a user to his 'own' page in Jersey REST service

How to authenticate and redirect a user to his own page i.e to www.mysite.com/"user's email".
I am using the following algo which is not working...
userDB in User class:
Map<String,String> userdata=new HashMap<String,String>();
First my login process form :
#Path("/login")
#POST
#Produces(MediaType.TEXT_HTML)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void login(
#FormParam("email") String emailc,
#FormParam("password") String pass,
#Context HttpServletResponse servletResponse
) throws IOException,RuntimeException {
User u1=new User();
pass=u1.getPassword();
emailc=u1.getEmailaddrs();
boolean checked=false;
boolean exists;
exists=u1.userdata.containsKey(emailc);
if(exists){
String mypass =u1.userdata.get(emailc);
if(mypass==pass){
checked=true;
}else{
checked=false;
}
}else{
checked=false;
}
if(!checked){
//User Doesn't exists
servletResponse.sendRedirect("http://localhost:8080/MySite/pages/Create_Profile.html");
}else{
servletResponse.sendRedirect("http://localhost:8080/MySite/{email}"); <<<< How to redirect using #FormParam("email")
}
}
createprofile
#POST
#Produces(MediaType.TEXT_HTML)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void newUser(
#FormParam("email") String email,
#FormParam("password") String password,
#Context HttpServletResponse servletResponse
) throws IOException {
User u = new User(email,password);
User.userdata.put(email,password);
}
Your usage of userdata [Map] looks wrong to me. Is it a part of user class, is it non static or static ?
If it is non static then every time you will do new User() .. that map will be initialized and it will have no data in it. Hence u1.userdata.containsKey(emailc); will be always false.
If you are using a hashmap as a temporary database for dev purposes then, make it static rather keep it in a different class like UserStore or some DB access layer. Exmaple below:
public class UserDAO(){
private static Map<String,User> userdata = new HashMap<String,User>();
public boolean hasUser(String email){
return userdata.contains(email);
}
public User saveUser(String email, String password ...){
//make user object save it in map and return the same
}
// more methods for delete and edit etc.
}
And use this in your REST layer classes like this
exists = userDao.hasUser(email);
Advantages :
Your problem will be solved.
Later on when you move to actual db implementation you will just have to change your UserDao code and rest application code will be just fine. -- Loose coupling :)
Also regarding forward using email
servletResponse.sendRedirect("http://localhost:8080/MySite/{email}"); <<<< How to redirect using #FormParam("email")
add the email parameter there in the url only, if thats what you want:
servletResponse.sendRedirect("http://localhost:8080/MySite/"+emailc);
UPDATE :
See the fundamental thing is that you get request parameters [email , password]. You check it whether it is present in map or not. Now what you are doing wrong here is you create a new user like this User u = new User(); and then get email and password from it emailc = u.getEmail();. This emailc will always be null and your userdata map will always return false for that. You have two choices :
Either set email and password in user object and then get the data from user object.
Use the email and password obtained from request parameters for your logic. Do not alter them
One good practice to follow while programming is that at all times think of your method parameters as final parameters.
UPDATE 2 :
if(mypass==pass){
checked=true;
}else{
checked=false;
}
Change == to equals method. String matching should be done by equals or equalsIgnoreCase method not ==.
You always create a new User without any parameters: User u1=new User();. All these User instances will have the same property values and probably exists is always false.

facebook4j OAuth issue

I am using facebook4j i have set the configuartion details in facebook4j.properties file. But when i trying to get the accesstoken it shows
SEVERE: Error while creating the Access TokenOAuth app id/secret combination not supplied
java.lang.IllegalStateException: OAuth app id/secret combination not supplied
at facebook4j.FacebookBaseImpl.getOAuth(FacebookBaseImpl.java:247)
at facebook4j.FacebookBaseImpl.getOAuthAuthorizationURL(FacebookBaseImpl.java:213)
at facebook4j.FacebookBaseImpl.getOAuthAuthorizationURL(FacebookBaseImpl.java:206)
Could anyone can provide a example for the facebook4j for java console application
Facebook facebookClient = new FacebookFactory().getInstance();
return facebookClient;
This is how you could use facebook4j without external configuration files. The code below provides a minimal example.
Here is my simple demo:
import facebook4j.Facebook;
import facebook4j.FacebookException;
import facebook4j.FacebookFactory;
import facebook4j.auth.AccessToken;
public class Facebook4JMinimalExample {
/**
* A simple Facebook4J client.
*
*
* #param args
* #throws FacebookException
*/
public static void main(String[] args) throws FacebookException {
// Generate facebook instance.
Facebook facebook = new FacebookFactory().getInstance();
// Use default values for oauth app id.
facebook.setOAuthAppId("", "");
// Get an access token from:
// https://developers.facebook.com/tools/explorer
// Copy and paste it below.
String accessTokenString = "PASTE_YOUR_ACCESS_TOKEN_STRING_HERE";
AccessToken at = new AccessToken(accessTokenString);
// Set access token.
facebook.setOAuthAccessToken(at);
// We're done.
// Write some stuff to your wall.
facebook.postStatusMessage("Wow, it works...");
}
}
Note that it is important to FIRST make a call to "facebook.setOAuthAppId(..)" and THEN set the access token. Otherwise you'll get an IllegalStateException saying "OAuth app id/secret combination not supplied".
In this case, I've just used a default value for OAuthAppId.

Facebook with DotNetOpenAuth 4.1.0.12182

I'm attempting to create a user login for Facebook and Windows LiveId using DotNetOpenAuth 4.1.0.12182
However the examples in the download make use of DotNetOpenAuth.ApplicationBlock and DotNetOpenAuth.ApplicationBlock.Facebook which don't exist in the current build.
Instead there is the DotNetOpenAuth.AspNet.Clients namespace which includes FacebookClient and WindowsLiveClient - however I can't find any example of how to use these.
Do any examples or documentation exist?
I have been able to get DNOA version 4.1.0.12182, .Net 3.5 and Facebook to work with each other by creating a FacebookAuthClient that is derived off of the DotNetOpenAuth.OAuth2.WebServerClient. One little gotcha that I have found is that if you are using cookie based sessions then you have to access the session before you use the OAuth functionality. From what I can tell this is because DNOA uses the Session ID as the state parameter and if session has never been accessed it can change between requests. This will cause a state parameter mismatch error when the response comes back from Facebook.
FacebookAuthClient:
public class FacebookAuthClient : DotNetOpenAuth.OAuth2.WebServerClient
{
private static readonly DotNetOpenAuth.OAuth2.AuthorizationServerDescription Description = new DotNetOpenAuth.OAuth2.AuthorizationServerDescription
{
TokenEndpoint = new Uri("https://graph.facebook.com/oauth/access_token"),
AuthorzationEndpoint = new Uri("https://graph.facebook.com/oauth/authorize")
};
public static readonly string [] ScopeNeeded = { "publish_stream" };
public FacebookAuthClient()
: base(Description)
{
}
}
Facebook.aspx.cs:
public partial class FacebookPage : System.Web.UI.Page
{
private FacebookAuthClient _client = new FacebookAuthClient
{
ClientIdentifier = ConfigurationManager.AppSettings["FBClientId"], //The FB app's Id
ClientCredentialApplicator = DotNetOpenAuth.OAuth2.ClientCredentialApplicator.PostParameter(ConfigurationManager.AppSettings["FBClientSecret"]) // The FB app's secret
}
protected void Page_Load(object sender, EventArgs e)
{
DotNetOpenAuth.OAuth2.IAuthorizationState auth = _client.ProcessUserAuthorization();
if (_auth == null)
{
// Kick off authorization request with the required scope info
client.RequestUserAuthorization(FacebookAuthClient.ScopeNeeded);
}
}
}
This is just a test app so there is no error handling but it seems to work.
Edit
I used the DotNetOpenAuth(unified) NuGet package for all of this.
Edit
Added missing .PostParameter call to the creating of the ClientCredentialApplicator.
You'll need to use ctp version 3.5 of DNOA. Version 4+ has been made to work with a later draft of OAuth 2 then Facebook uses.
You can find it on the owners GitHub:
https://github.com/AArnott/dotnetopenid

Amazon S3 client based on SOAP

I need a Win client for Amazon S3 that utilizes SOAP protocol for all transactions. As far as I see most solutions are REST based rather than SOAP. Any ideas?
EDIT:
Just want to clarify: please do not suggest using REST instead. I am perfectly aware of what can or cannot be done with either protocol. So if I ask for this specific solution, there is a reason for that.
What I need is a working software for Win platform that utilizes SOAP for Amazon S3, not suggestions how to do my job. Thank you.
Start Visual Studio 2008, create a new C# Windows console application.
Add the S3 WSDL as a service reference. In Solution Explorer, right click References, select Add Service Reference. Type in the S3 WSDL address in the Address box: http://s3.amazonaws.com/doc/2006-03-01/AmazonS3.wsdl. Click Go. "AmazonS3" should show in the Services box. Enter a namespace. I entered Amazon.S3. Click OK.
Modify Program.cs to look something like the following:
using System;
using System.Globalization;
using System.Text;
using System.Security.Cryptography;
using ConsoleApplication1.Amazon.S3;
namespace ConsoleApplication1 {
class Program {
private const string accessKeyId = "YOURACCESSKEYIDHERE0";
private const string secretAccessKey = "YOURSECRETACCESSKEYHEREANDYESITSTHATLONG";
public static DateTime LocalNow() {
DateTime now = DateTime.Now;
return new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, now.Millisecond, DateTimeKind.Local);
}
public static string SignRequest(string secret, string operation, DateTime timestamp) {
HMACSHA1 hmac = new HMACSHA1(Encoding.UTF8.GetBytes(secret));
string isoTimeStamp = timestamp.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture);
string signMe = "AmazonS3" + operation + isoTimeStamp;
string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(signMe)));
return signature;
}
static void Main(string[] args) {
DateTime now = LocalNow();
AmazonS3Client client = new AmazonS3Client();
var result = client.ListAllMyBuckets(
accessKeyId,
now,
SignRequest(secretAccessKey, "ListAllMyBuckets", now));
foreach (var bucket in result.Buckets) {
Console.WriteLine(bucket.Name);
}
}
}
}
If you now insert your access key ID and secret access key in the appropriate spots and run the program, you should get a listing of your S3 buckets.
The AmazonS3Client class has all the SOAP operations available as instance methods on it.
The Amazon website carries an older (VS2005 + WSE) C#/SOAP sample at http://developer.amazonwebservices.com/connect/entry.jspa?externalID=129&categoryID=47.
EDIT: posted a visual studio solution at http://flyingpies.wordpress.com/2009/08/04/the-shortest-ever-s3-csoapwcf-client/.