This forum is now a read-only archive. All commenting, posting, registration services have been turned off. Those needing community support and/or wanting to ask questions should refer to the Tag/Forum map, and to http://spring.io/questions for a curated list of stackoverflow tags that Pivotal engineers, and the community, monitor.

400 Bad Request

Aug 12th, 2012, 11:53 AM

Hi,

I have tried to connect to Facebook with Spring Social but it didn't work - I always get this exception trace above.
Does anybody know what I' am doing wrong? The accessToken is the right one, also appl ID. Secret Key is faced.
Thanks a lot for help!
Generic1

It's clear from looking at this that you're misusing exchangeForAccess(). The proper way to use that method is to exchange an authorization code for an access grant (which contains the access token value). But it looks like you're trying to exchange an access token for an access token, which isn't correct.

What is supposed to happen is that you redirect your user's browser to the authorization URL where they will accept or deny authorization. Assuming that they accept, then Facebook will redirect them back to your application with an authorization code as a query parameter. It's this authorization code that you pass to exchangeForAccess() to get an access token (and then you can create a connection, use the token to access the API, or whatever it is you'd like to do.

What puzzles me more, however, is why you're trying to implement the OAuth2 authorization flow with Facebook when Spring Social already implements that with ConnectController? Everything that it appears that you're trying to do in HomeController is already handled by ConnectController for you, so why not use that?

Comment

Hi,
Thanks a lot for your help - I was not sure about ConnectController does all the things. I read a tutorial where it was explained like I did above.
Now I have tried to create my example like in this tutorialhttp://static.springsource.org/sprin...onnecting.html
but I have still some problems.
The ControllerConnection- Controller isn't invoked after clicking the login- button - I get a HTTP 404 code - the ConnectionController for /connect/twitter can't be found.
For me it is not clear where I have made the fault - at the ViewResolver or the Spring Social config.
Here my ViewResolver:

Whats still not clear for me is, where I can change the redirect- URL for Twitter. Now I had to make the structure WEB-INF/jsp/connect/twitterConnected.jsp and there I am redirected after login at twitter. But the redirection for my application should be WEB-INF/jsp/home.jsp.
Is there a possibility to redirect to my home.jsp?

And I would have a further question: before the redirection, where can I get the Twitter- API to set the Name and Profile- image into the session of my web application in order to show the name und profile image after login?

Thanks a lot for your help!!
Generic

Comment

I'm glad you got it to work, but...you could've accomplished the same thing without component-scanning and simply explicitly configuring ConnectController. That's how all of the samples at https://github.com/SpringSource/spring-social-samples do it. And if you explicitly configure it, then you don't have to exclude ProviderSignInController.

As for the redirect: It *must* come back to ConnectController so that ConnectController can exchange the authorization code/verifier for an access token and complete the connection. And, ConnectController then sends the request to the view whose logical view name is "connect/{provider name}Connected"...in your case that is WEB-INF/jsp/connect/twitterConnected.jsp. You can make it go to any view you want, however, by subclassing ConnectController and overriding the connectView() method to return whatever view name you want (you can even use a "redirect:" prefix to do a redirect if you'd like...for example, it could return "redirect:/home").

Comment

What's the URL when handling the redirect? Its path should be /connect/twitter. If it's not, then what is it? Is it /connect/null? If so, I feel like I'm missing something from your config that would explain this.

Comment

I had a look at your code earlier and couldn't spot what was wrong, but I think I've just realised what's missing - it's the @PathVariable annotation before the providerId parameter in the method signature.

Comment

Just to add to my previous comment.. while I believe adding the @PathVariable to the overridden callback method will resolve this issue, I'm not sure you need to be overriding this method at all.

To override the default status views you should only need override the connectView methods. I've just tried a simple local example - subclassing ConnectController with these methods overridden and the app respected these overrides and redirected to my custom views. I also had a ConnectInterceptor wired in whose postConnect method was called, so you shouldn't need to override the callback for this reason.

I may have missed something here, there may be something else in your setup which means you'd like to override the callback method, but in theory you shouldn't need to.

Hope this helps,

Michael

Comment

Michael's right. If all you're doing is calling super.oauth1Callback() in the overriding method, then there's really no reason to override that method at all. (But if you do, be sure to annotate the providerId parameter with @PathVariable).

While we're on the topic, I've been wondering for a *long* time about overriding the connectView() method versus having a connectView property that can be configured in Spring. Certainly, overriding connectView() gives more flexibility in the sense that you could construct the returned value intelligently using whatever facilities Java offers...but I also think that the most common case would be a view that is expressed as a simple String (and thus, can be easily configured via Spring injection without creating a subclass of ConnectController). Curious what your thoughts are?

>> Curious what your thoughts are?
Actually my Spring experiences are a bit outdated. The last 6 years I have used OSGi and there override Methodes is common.
But thanks for the hint. I think I will configure it via Spring injection.

Comment

I would have one last question.
For JdbcUsersConnectionRepository I need a dataSource (in my real web application it is a mysql connection) and in my MySQL Database I need a table like the SQL at the bottom. And in this table the user logged in over e.g. twitter where stored. Am I right or did I have something misunderstood?
Thanks once again.

By the way, if you are interested why I need all this things. We will implement Spring Social at this web application: http://www.atleticus.net

Comment

With regards to Craig's question about overriding connectView() vs. having an injectable property, my personal opinion is that I like to keep the consistency and default behaviour of the current implementation, but I'd like to be able to customise this behaviour without subclassing. Ideally I'd like to be able to augment behaviour of an existing Spring Social webapp, allowing configurations to be changed through properties/composition rather than inheritance.

Considering my own use-case using spring-social-security :

I'd like to have a shared view which has connection options to available providers dynamically generated - a single jsp for example which accepts a "providerId" attribute and displays the relevant connect with provider buttons, or displays all provider connect options if this parameter is not present. Using the existing implementation of ConnectController, I've needed to create logical views for each provider (tiles definitions) - each referencing the same underlying jsp and passing in a "providerId" attribute to the jsp.

In this use-case, I'm registering new providers using component-scanning - having to create provider-specific views for essentially shared behaviour isn't as clean a solution as I'd like, and limits an application's ability to add new providers dynamically.

If ConnectController were able to be configured with its connectView through a property, this would remove the need to create these provider-specific views, *if* the relevant providerId were passed into the view as a model attribute for example.

I was wondering whether a hybrid approach may be possible? - to encapsulate the existing view name creation logic into a strategy class which can be injected into the ConnectController. This strategy could be set to the current strategy by default, but applications could inject their own alternatives - in my case a strategy to building up a single view with a model attribute set for the providerId.

This would allow new providers to be added (in my case through component-scanning) without the application needing to make provider-specific amendments.

(As an aside, if ConnectController were to go in this direction, I feel that the connectionStatusRedirect method would also need to be customisable in the same was as connectView).

Just my 2 cents worth - I think there are pros and cons to each approach and can see why it's a tricky issue to determine to the best approach.

Comment

Generic1: Yes, you'll need to create a table somewhat like what you described or as is described in JdbcUsersConnectionRepository.sql. Note, however, that JdbcUsersConnectionRepository.sql serves only as a guideline for how such a table should be created and may not work with all databases--you may need to tweak the schema to accomodate the quirks of whatever DB you're using.

I think you have a good understanding of what that table is used for, but to clarify the terminology: When you say "user logged in over e.g. twitter", it's actually an authorization process, not an authentication process--that is, the user is authorizing your application to access their data and post updates on Twitter. At the end of that authorization process (OAuth 1.0a in the case of Twitter), your application receives an access token and secret. On Twitter's end, they're already associating your application, the user, and the token/secret in whatever DB they use. Within a Spring Social-enabled application, the user connection repository (and the underlying table) is what keeps track of that relationship between your user, your application, and Twitter. We call that relationship a "connection".

To be clear again, ConnectController's job is to orchestrate the connection process, which is an authorization process. That said, the authorization process can be used as a form of authentication as well. ProviderSignInController is a Spring Social controller that can be used to orchestrate the connection process in such a way that the user ends up authenticated into your application.