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.
Related
I have a SpringBoot OAuth2 Client and ResourceServer. My AuthorizationServer is Okta.
Now suppose that in a certain moment I want to add a claim to my token, for Example:
#GetMapping("/addIdUser")
public ResponseEntity<String> addUser(#AuthenticationPrincipal Jwt jwt) {
// here I want to add a claim to my Jwt, the token
// should return to the frontend and when I resend back to my resourceserver
// it should be validated again
return new ResponseEntity<String>(token, HttpStatus.OK);
}
I have read tons of docs of TokenEnhencer and TokenConverter but it not seems to be the solution I looking for.
Can I do something like this?
Seems like you want to authorize based on domain specific claims, and there are two main options here:
Get extra claims at the time of token issuance - Okta needs to either call an API or do a database lookup - this is the preferred option but not always possible
Look up claims in the resource server when an access token is first received, then cache them for subsequent requests with the same access token
Leave the Okta issued token alone in the client, then adopt one of the above two approaches in the API. Out of interest, here is a Spring Boot API of mine that uses a library based approach to OAuth handling and implements both approaches:
Standard Authorizer
Claims Caching Authorizer
I have a situation I haven't run into yet and wondering if I need to write a custom authorize attribute to handle this situation or if there is something in the identity framework I should be using.
I need to support both Implicit flow (mostly for swaggerUI integration) and client credential grant in my webapi. The data I'm working with is sensitive and therefore I don't want anyone who discovers my swagger page and can authenticate with my AAD instance (through an implicit flow) to be able to consume my data. I want to restrict the my api to look for roles in the jwt IF THEY ARE PRESENT.
On the flip side my WebApi is most likely going to be consumed by other services. So I need to support client credential flow. Obviously the tokens issued through the client credentials grant will not have a role claim, so I can't look for roles when I authorize these requests.
I'm basically looking for something like this:
[Authorize(Roles = "swagger_admin", Optional=true)]
public class UserController : ApiController
{
But I'm not seeing something logically equivalant, and before I go out and write a custom authorize attribute I want to know what others have done here.
Thanks!
I have an Identity Server 3 based Authentication service. It's currently using JWTs, but I'm planning to switch over to reference tokens so that we can revoke them when the user logs out of the client application. I've been researching this (Dominick Baier - Reference Tokens and Introspection) and understand that one option - the one I'd like to implement - is to have my user service - part of my authentication service implementation - use the Identity Server ITokenHandle interface to revoke the token. I have not been able to find any more information on this interface or how to implement it in my user service.
Has anyone done Identity Server 3 token revocation in their user service or can anyone point me to more information about this approach?
The two GitHub postings in the comments on the original post contained the information I needed. I was able to switch from JWTs to reference tokens and then implement automatic revocation of the reference tokens on user sign out. The switch of the token type was a simple matter of setting
AccessTokenType = AccessTokenType.Reference
in my client setup code. To revoke the tokens on sign out I first added
idSrvFactory.Register(new Registration<DefaultClientPermissionsService>());
in Startup.cs. Then in my UserService, I added it to the UserService constructor
public UserService(DefaultClientPermissionsService clientPermissionsSvc)
{
_clientPermissionsSvc = clientPermissionsSvc;
}
Then finally, still in my UserService, I implemented
public override Task SignOutAsync(SignOutContext context)
{
string subjectId = GetSubjectId(context);
_clientPermissionsSvc.RevokeClientPermissionsAsync(subjectId, context.ClientId);
return Task.FromResult(0);
}
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/
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.