Spring Boot Facebook Starter how to login several users? how to obtain accessToken or providerId - spring

I've followed several tutorials and got really close to nowhere understanding spring integration with facebook API, having strong knowledge in other spring modules I found myself surprised...
Every tutorial uses:
public <A> Connection<A> findPrimaryConnection(Class<A> apiType) {
String providerId = getProviderId(apiType);
if (connections.containsKey(providerId)) {
return (Connection<A>) connections.get(providerId).get(0);
}
return null;
}
As this returns me first connection every time?
I've tried connecting to my app from two different machines and both requests return same facebook profile..
So as usual I went to investigate api what is required to obtain user-specific-connection when stumbled upon method which does what I want:
public <A> Connection<A> getConnection(Class<A> apiType, String providerUserId) {
return (Connection<A>) getConnection(new ConnectionKey(getProviderId(apiType), providerUserId));
}
Ok, so I went trying to figure out how to obtain providerId... I fail, many questions such as:
How to get providerUserId by providerId, accessToken and secret? (Spring Social)
don't make it clearer.
It seems I am not the first to fail understand philosophy of Spring integration with facebook. As to many of us it is obvious that we want to use advanced features where every user needs to have it's own connection to facebook with its own data returned and possibility to login via facebook.
Could you kindly please explain how to get connection/facebook object per user as I am very disoriented by the implementation of this spring module.
Does Spring Social Facebook even support concurrent users logged in to Facebook? It all feels to me like building beautiful Eiffel tower without any doors.
I didn't use Spring Security integration as I felt ConnectController approach will provide more control, but apparently it does not and has biased assumptions. Now looking at Spring Security integration.

I tried thi myself some month ago and found it also very confusing.
For me it looked like as if all this spring-social stuff is trying to identify a user of your web-app interactively using OAuth.
What I was looking for was connecting my spring application to facebook to e.g. post something there.
For this purpose you can use the FacebookTemplate and forget about the provider etc. :
public String postOnFacebook(Machine machine, String url) {
Facebook facebook = new FacebookTemplate(accessToken);
FacebookLink link = createLink(machine, url);
// the first parm is the title on top of the message
String message = facebook.feedOperations().postLink("message", link);
return message;
}
You need an accessToken for the facebook account, which is a different story. Finally this helped :
http://www.slickremix.com/facebook-60-day-user-access-token-generator/

Related

MVC Prompt Query Parameter

I want to override Azure AD SSO login for a MVC web application. I don't want to log other applications out in the process, but require login for security purposes. I am using OAuth2.0 with OIDC via Owin for authentication.
I am trying to use the prompt=login query parameter, which should theoretically do the trick. I found a Github reference to this being recently made available in Core but cannot trace how to do it in MVC5.2
Is it possible to do it in the Application Builder? I tried adding .WithExtraQueryParameters ("prompt=login") to the ConfidentialClientApplicationBuilder when getting the access code. No luck.
Is there another workaround if the code doesn't come out-of-the-box?
EDIT: PublicClientApplication allows .WithPrompt(Prompt.Login) while ConfidentialClientApplication does not (also does not allow AcquireTokenInteractive) This is a web app so it needs the confidential builder. Tested using the Public builder and it logs in successfully. But I get an ActiveX instantiation error 'not in a single-threaded apartment'(?) Strange, unless that is how the token is being delivered perhaps. I also tested by changing to multitenant in Azure and by toggling Public client on and off.
Any ideas?
You could use ForceLogin to add paramter to ConfidentialClientApplicationBuilder.
ForceLogin: enables the application developer to have the user prompted for credentials by the service even if this would not be needed. This can be useful if Acquiring a token fails, to let the user re-sign-in. This is done by sending prompt=login to the identity provider. Again, we've seen it used in some security focused applications where the organization governance demands that the user re-logs-in each time they access specific parts of an application.
So, use the code as below:
result = await app.AcquireTokenInteractive(scopes)
.WithPrompt(Prompt.ForceLogin)
.ExecuteAsync();
The Modifier .WithExtraQueryParameters will not help you. You need to use .WithPrompt instead.Please refer article.
Example:
await PublicClientApplication
.AcquireTokenInteractive(scopes, null)
.WithAccount(CurrentUser)
.WithPrompt(Prompt.ForceLogin) // use login for your case
.ExecuteAsync();
I eventually resolved this as follows:
Under Notifications in the ConfigureAuth(IAppBuilder app) add a reference to a new task:
RedirectToIdentityProvider = OnRedirectToIdentityProvider,
Then add the task:
private Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification
<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
// Forces the user to login.
if (notification.ProtocolMessage.Prompt == null)
{
notification.ProtocolMessage.Prompt = "login";
}
return Task.FromResult(0);
}
Hope that helps the next person with this issue.

ASP.net Web API RESTful web service + Basic authentication

I'm implementing a RESTful web service using ASP.Net Web Api. I have concluded to use Basic authentication + SSL to do the authentication part. What is the best/correct way to implement that?
My first attempt was to do it manually, parsing the Authorization header, decoding and verifying the user against my database. It works, but I wonder if I am missing something.
I've seen some solutions using user roles and principals. While I'm not sure what these actually do, I'm almost sure I will not be needing these, since in my database I define my own users and their roles.
Also what I haven't yet completely understand, is if the consumers of the service must sent the credentials with each request or they are somehow cached. Should my service do something in order for this to happen, or it's completely up to the consumer to handle this?
And a last question about clients making requests with javascript. Would there be any "cross domain request" problems if they try to use the service?
Jamie Kurtze provides a good explanation of using Basic Authentication here ASP.NET Web API REST Security Basics
From my understanding, if you want your requests to be stateless then each request will require the Authentication field to be set
Jamie Kurtze wraps the necessary code in a class derived from DelegateHandler, while Rick Strahl checks if the call is valid using a Filter. You can read more at his blog post on this topic at A WebAPI Basic Authentication Authorization Filter
Use basic authentication for the initial (sign in) request by adding a [BasicHttpAuthorize] attribute to the appropriate controllers/methods. Specify the Users and Roles with the attribute if desired. Define BasicHttpAuthorizeAttribute as a specialized AuthorizeAttribute like this:
public class BasicHttpAuthorizeAttribute : AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext actionContext)
{
if (Thread.CurrentPrincipal.Identity.Name.Length == 0) { // If an identity has not already been established by other means:
AuthenticationHeaderValue auth = actionContext.Request.Headers.Authorization;
if (string.Compare(auth.Scheme, "Basic", StringComparison.OrdinalIgnoreCase) == 0) {
string credentials = UTF8Encoding.UTF8.GetString(Convert.FromBase64String(auth.Parameter));
int separatorIndex = credentials.IndexOf(':');
if (separatorIndex >= 0) {
string userName = credentials.Substring(0, separatorIndex);
string password = credentials.Substring(separatorIndex + 1);
if (Membership.ValidateUser(userName, password))
Thread.CurrentPrincipal = actionContext.ControllerContext.RequestContext.Principal = new GenericPrincipal(new GenericIdentity(userName, "Basic"), System.Web.Security.Roles.Provider.GetRolesForUser(userName));
}
}
}
return base.IsAuthorized(actionContext);
}
}
Have the initial response include an API key for the user. Use the API key for subsequent calls. That way, the client's authentication remains valid even if the user changes username or password. However, when changing password, give the user an option to "disconnect clients", which you implement by deleting the API key on the server.
Have a look here for a good basic authentication implementation
http://leastprivilege.com/2013/04/22/web-api-security-basic-authentication-with-thinktecture-identitymodel-authenticationhandler/
there is more to read about it at:
https://github.com/thinktecture/Thinktecture.IdentityModel.45/wiki

MissingAuthorizationException: Getting last tweets

Why is it needed to be authorized when I just want the last 2 tweets?
I would like to create a minimal config as I don't need the connection stuff.
And as I understand the twitter api it is not necessary to have a consumerKey/consumerSecret for just getting some tweets?!
Bean:
<bean id="twitter" class="org.springframework.social.twitter.api.impl.TwitterTemplate" />
Spring Controller:
#Controller
public class FragmentController {
#Autowired
private Twitter twitter;
#ModelAttribute
public void global(ModelMap map) {
map.addAttribute("tweets", twitter.timelineOperations().getUserTimeline("myTwitterUsername", 2));
}
#RequestMapping("index.html")
public String index() {
return "index";
}
}
As of the release of version 1.1 of Twitter's API, all operations against the API require authorization, including those that you would think do not need it.
That said, you do not necessarily need user authorization to request resources that would otherwise be public and not private to any specific user. A specified user's tweets, for instance, can be had without user authorization. But you still need application authorization.
This is where Twitter's API gets a bit weird. For user authorization, Twitter is secured with OAuth 1.0a and this applies to all (or most all) resources at Twitter. For app-only authorization, Twitter uses OAuth 2 client credentials grant. This kind of authorization applies to a subset of the whole API.
Fortunately, Spring Social supports this in the very latest snapshot build (1.1.0.BUILD-SNAPSHOT). Via OAuth2Template, you can call authenticateClient() to obtain an AccessGrant (and from that obtain an access token). Then you can create an instance of TwitterTemplate, passing in only the client's access token and use it to access Twitter's API for those operations that access app-only authorization.
Know that when I say "very latest snapshot build", that's quite literal. I pushed the changes to TwitterTemplate last last night and it could still stand some more testing. I have tested it a bit with regard to search, but all other resources are relatively untested. If you run into any issues, please let me know by creating a bug issue at https://jira.springsource.org/browse/SOCIALTW.

Retrieve blog feeds using google oauth 2.0 and scribe

I used scribe to connect to google using oAuth 2.0 and successfully got the access token. When i am trying to get the blogs i always get the below error
Unauthorized
Must authenticate to use 'default' user
Below is the code snippet
GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
oauthParameters.setOAuthConsumerKey(CONSUMER_KEY);
oauthParameters.setOAuthConsumerSecret(CONSUMER_SECRET_KEY);
oauthParameters.setScope("http://www.blogger.com/feeds");
oauthParameters.setOAuthToken(ACCESS_TOKEN);
oauthParameters.setOAuthTokenSecret(ACCESS_TOKEN_SECRET); // this is null
BloggerService myService = new BloggerService("blogger");
try {
myService.setOAuthCredentials(oauthParameters, new OAuthHmacSha1Signer());
} catch (OAuthException e) {
e.printStackTrace();
}
final URL feedUrl = new URL("http://www.blogger.com/feeds/default/blogs");
Query query = new Query(feedUrl);
Feed resultFeed = myService.getFeed(query, Feed.class);
Not able to get the feeds here and displays the Unauthorized error as mentioned above.
Jason has answered your question, I believe.
You do not want to use the library code above to access blogger. Use the new API, and use OAuth2 https://developers.google.com/blogger/docs/3.0/using#auth
I'm not sure what scribe is, but with OAuth2, you need to indicate what type of application you're building, It might be one that runs from a web server, or an installed application. What's you've determined that, you can follow the appropriate documentation for the java client library linked to above to get the access token and retrieve the data.

Spring Social Twitter Oauth

I want to use spring social to develop an twitter app which will update status and upload photos.I am not able to understand how to do Oauth authentication using Spring social.All examples I saw talks about hardcoding the accesstoken which would work only for that particular user.I dont want to hardcode anything except the app keys.
Kindly some one explain me how to do Twitter Oauth using spring social.I went through the official documentation of spring framework but got confused when I saw the other examples..
Thanks
I saw talks about hardcoding the accesstoken which would work only for that particular user.I dont want to hardcode anything except the app keys.
"app keys" a.k.a. consumer { key, secret } pair authorizes your app to use Twitter APIs that do not require user authentication. Think about it as you app browsing a twitter website without being logged in. Hence you'd have an ability to search, get timelines, etc.. => read only.
In case you'd like to post something back, you'd have to make you app do that on behalf of a real Twitter account / user. Think about someone writing a Twitter client => it can be downloaded by many different users, hence it needs two things to function properly:
Be a registered Twitter application => have consumer { key, secret } pair
Be able to post tweets / images on behalf of the user => have access { token, secret } pair
In order to get that access { token, secret } pair, you'd have to have an "OK" from that user/account.
That is where OAuth comes in => it sends the user to the confirmation page, where he clicks "OK, I allow this app to post on my behalf". This "OK" then gets converted to the OAuthToken that your app can use.
If all you want is to post updates on behalf of yourself, then you need to approve your own Twitter app, and persist that OAuthToken to be used by your app.
Unfortunately Twitter does not yet support OAuth 2.0, hence you'd have to do more... You'd have to do OAuth 1.0a.
Spring Social documentation describes the OAuth 1.0a flow here, where you can see the flow visually.
On order to "code" this flow using Spring Social APIs, you should first request access {token, value} pair ( there is a convenience ConnectController for it btw ):
TwitterConnectionFactory connectionFactory =
new TwitterConnectionFactory( "consumerKey", "consumerSecret" );
OAuth1Operations oauthOperations = connectionFactory.getOAuthOperations();
OAuthToken requestToken = oauthOperations.fetchRequestToken( "https://my-callback-url", null );
String authorizeUrl = oauthOperations.buildAuthorizeUrl( requestToken, OAuth1Parameters.NONE );
response.sendRedirect( authorizeUrl );
And once it comes back (to your callback URL) you can use OAuth1Operations to get OAuthToken which is exactly that pair.
// upon receiving the callback from the provider:
OAuthToken accessToken = oauthOperations.exchangeForAccessToken(
new AuthorizedRequestToken(requestToken, oauthVerifier), null);
Now, as you have all you need, you have choices:
Create a TwitterTemplate from that OAuthToken:
String consumerKey = "..."; // The application's consumer key
String consumerSecret = "..."; // The application's consumer secret
String accessToken = accessToken.getValue();
String accessTokenSecret = accessToken.getSecret();
Twitter twitter = new TwitterTemplate( consumerKey, consumerSecret, accessToken, accessTokenSecret );
Create a Twitter Connection object
Connection<Twitter> connection = connectionFactory.createConnection( accessToken );
Once you get the Connection, you might want to persist it via ConnectionRepository as shown here, so you don't have to go through obtaining access token again.
Here is Connection API.
The previous answer is good, but is only part of the story...
There are at least 3 levels at which you may work with Spring Social: (1) Using the TwitterTemplate directly, in which case you'd need to obtain the access token and secret through some means of your own, (2) use OAuth1Template, perhaps through TwitterConnectionFactory as the previous answer showed, to get the access token and from that create the TwitterTemplate, in which case you'd have to handle the redirects and callbacks yourself or (3) use Spring Social's ConnectController to handle everything for you.
Using ConnectController involves the least amount of OAuth work on your part. You just configure the appropriate pieces in Spring and ConnectController takes care of the rest. See http://static.springsource.org/spring-social/docs/1.0.x/reference/html/connecting.html for details.
I encourage you to have a look at the Spring Social Showcase sample at https://github.com/SpringSource/spring-social-samples. It uses ConnectController to handle by Twitter and Facebook connections. And, of course, you're welcome to ask questions on the Spring Social forum at http://forum.springsource.org/forumdisplay.php?82-Social.

Resources