I am having a website (Angular App) which I can reach on https://localhost:4200 and a server (pure REST API) that is on https://localhost:8443.
Since the REST endpoints are secured, a user must login on my server. Obviously I want users to be able to signup using Facebook and further communicate with my server after login.
According to the docs
POST /signin/{providerId}
– Initiates the sign in flow.
that is why there is a button that does just this:
<form ngNoForm name="fb_signin" id="fb_signin" action="https://localhost:8443/signin/facebook" method="POST">
<input type="hidden" name="scope" value="email">
<button type="submit">SIGNING</button>
</form>
From there, everything works fine for some time. The user gets redirected to Facebook’s authorization page where the authorization button gets clicked. After that the user gets redirected to https://localhost:8443/signin/facebook.
It seems that per default, in case the user is unknown, there will be a another redirect to https://localhost:8443/signup (see docs)
If the provider user ID matches more than one existing connection,
ProviderSignInController
will redirect to the application’s sign in URL to offer the user a chance to sign in through another provider or with their username and password. The request to the sign in URL will have an “error
” query parameter set to “multiple_users
” to indicate the problem so that the page can communicate it to the user. The default sign in URL is “/signin
” (relative to the application root), but can be customized by setting thesignInUrl
property.
On my serer this looks like this (borrowed from a sample application):
@RequestMapping(value = "/signup", method = RequestMethod.GET)
public SignUpForm signupForm(WebRequest request) {
Connection<?> connection = providerSignInUtils.getConnectionFromSession(request);
if (connection != null) {
request.setAttribute("message", new Message(MessageType.INFO, "Your " + StringUtils.capitalize(connection.getKey().getProviderId()) + " account is not associated with a Spring Social Showcase account. If you're new, please sign up."), WebRequest.SCOPE_REQUEST);
return SignUpForm.fromProviderUser(connection.fetchUserProfile());
} else {
return new SignUpForm();
}
}
And here are my issues:
First of all I need to know what I am supposed to do at this endpoint. The user authorized my app, but my server does not know the user yet so do I
connection.fetchUserProfile()
and save the new user to my database- something else?
Second, I do not know how I am supposed to redirect back to my website from here which, as explained, lies on https://localhost:4200. But of course, my server does not know that.
Is there a chance somebody can guide me through this?
This is the SocialConfig
@Configuration
@EnableSocial
public class SocialConfig implements SocialConfigurer {
private final static Logger LOGGER = LogManager.getLogger(SocialConfig.class);
@Value("${spring.social.facebook.appId}")
String facebookAppId;
@Value("${spring.social.facebook.appSecret}")
String facebookSecret;
@Autowired
private DataSource dataSource;
@Bean
@Scope(value="singleton", proxyMode = ScopedProxyMode.INTERFACES)
public ConnectionFactoryLocator connectionFactoryLocator() {
ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();
registry.addConnectionFactory(new FacebookConnectionFactory(
facebookAppId,
facebookSecret
));
return registry;
}
@Bean
@Scope(value="singleton", proxyMode=ScopedProxyMode.INTERFACES)
public UsersConnectionRepository usersConnectionRepository() {
return new JdbcUsersConnectionRepository(dataSource, connectionFactoryLocator(), Encryptors.noOpText());
}
@Override
public void addConnectionFactories(ConnectionFactoryConfigurer cfConfig, Environment env) {
LOGGER.debug("Adding connection factories");
cfConfig.addConnectionFactory(new FacebookConnectionFactory(
env.getProperty("facebook.clientId"),
env.getProperty("facebook.clientSecret")));
}
@Override
public UserIdSource getUserIdSource() {
return new AuthenticationNameUserIdSource();
}
@Override
public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
return new JdbcUsersConnectionRepository(dataSource, connectionFactoryLocator, Encryptors.noOpText());
}
@Bean
public ProviderSignInController providerSignInController(
ConnectionFactoryLocator connectionFactoryLocator,
UsersConnectionRepository usersConnectionRepository) {
ProviderSignInController controller = new ProviderSignInController(
connectionFactoryLocator,
usersConnectionRepository,
new SimpleSignInAdapter(new HttpSessionRequestCache()));
return controller;
}
@Bean
public RequestCache requestCache() {
return new HttpSessionRequestCache();
}
@Bean
public SignInAdapter signInAdapter() {
return new SimpleSignInAdapter(new HttpSessionRequestCache());
}
}
Maven dependencies related to Spring Social:
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-facebook</artifactId>
<version>3.0.0.M1</version>
</dependency>
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-security</artifactId>
<version>2.0.0.M4</version>
</dependency>
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-core</artifactId>
<version>2.0.0.M2</version>
</dependency>
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-config</artifactId>
<version>2.0.0.M2</version>
</dependency>
2
Answers
I think there is another best way of doing so .As your angular webapp
(https://localhost:4200) comprises of webLayer so directly redirecting via form action is not a better way.You can use Proxy Routing click here
Now in case of you are using you are using proxy routing u need to configure your proxy port (8443) by command.
then you need to first authenticate your each user/new user to your server(service layer) & then pass every request through user service layer controller .This will lead to pass every request through your server and it solve your problem.
This is my
signup
PoC code , FYIPoints to notes :
I retrieve the connection object set in
ProviderSignInController.handleSignIn()
, it contains freshy (not mapped in db) providerId/providerUserId pair.And I create a new local user , give it random username/password pair , and link the new providerId/providerUserId to the local user.
This is a simple PoC code , it should be modified to conform to your business logic.
Maybe you can display a form for user to fill-in his nickname or address or something. That’s depend on your business logic.