I am sharing the complete code regards to my problem.
I am taking the social configuration file handled via social-cfg.xml it is in classpath.
social-cfg.xml
google.client.id=#####################################################################
google.client.secret=############################
google.scope=https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile
I have made java handler to handle this config file
socialConfig.java
package com.inno.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.social.UserIdSource;
import org.springframework.social.config.annotation.ConnectionFactoryConfigurer;
import org.springframework.social.config.annotation.EnableSocial;
import org.springframework.social.config.annotation.SocialConfigurer;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.ConnectionRepository;
import org.springframework.social.connect.ConnectionSignUp;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository;
import org.springframework.social.connect.web.ConnectController;
import org.springframework.social.google.connect.GoogleConnectionFactory;
import org.springframework.social.security.AuthenticationNameUserIdSource;
import com.inno.dao.AppUserDAO;
import com.inno.service.ConnectionSignUpImpl;
#Configuration
#EnableSocial
// Load to Environment.
#PropertySource("classpath:social-cfg.properties")
public class SocialConfig implements SocialConfigurer {
private boolean autoSignUp = false;
#Autowired
private DataSource dataSource;
#Autowired
private AppUserDAO appUserDAO;
#Override
public void addConnectionFactories(ConnectionFactoryConfigurer cfConfig, Environment env) {
try {
this.autoSignUp = Boolean.parseBoolean(env.getProperty("social.auto-signup"));
} catch (Exception e) {
this.autoSignUp = false;
}
// Google
GoogleConnectionFactory gfactory = new GoogleConnectionFactory(//
env.getProperty("google.client.id"), //
env.getProperty("google.client.secret"));
gfactory.setScope(env.getProperty("google.scope"));
cfConfig.addConnectionFactory(gfactory);
}
//............. more code regards to another functionality.
when i am hitting this href
<a th:href="#{/auth/google}">Google</a>
<br />
Then it's redirecting to google page with error as below
Error: redirect_uri_mismatch
The redirect URI in the request, http://localhost:8787/auth/google, does not match the ones authorized for the OAuth client. To update the authorized redirect URIs, visit: https://console.developers.google.com/apis/credentials/oauthclient/#######?project=#######
when i visit https://console.developers.google.com/apis/credentials/oauthclient/#######?project=#######
there are two option's
Authorized JavaScript origins
Authorized redirect URIs
I have set both of them to validate with my webapp. I just don't where is the point which stuck out this issue. PLease help me out. Also ask for any other requirement if required.
redirect URI in the google developer console must exactly match where you are sending your request from. In your case the error message tells you exactly where you are sending your request form.
http://localhost:8787/auth/google
Which means that you need to have that exactly in the Google developer console under Authorized redirect URIs or the authentication sever will not accept your request.
Note Port must be included. Exactly means exactly with the exception of cased.
Related
I have a Spring application that is secured using Oauth provided by Twitch. What I am trying to do is make it so that when the user clicks the logout button they have to reenter their Twitch credentials to log back into the site. From the reading I have done my understanding of the situation is that single sign off is fairly hard to achieve with Oauth. That said, Twitch's API seems to indicate that there is a way to tell them to invalidate an Oauth token: https://dev.twitch.tv/docs/authentication#revoking-access-tokens.
I have seen some information about a prompt=login parameter in OIDC but I have not been able to find any information about it or how to use it (on top of that I'm pretty sure that will require the users to reenter their credentials EVERY time rather than simply when they logout).
My initial approach to this problem was the number 1 answer in this thread but that did not actually change anything. I still was not required to enter my credentials upon trying to access one of the restricted endpoints, Spring simply quickly reauthenticated with Twitch and sent me through.
My current approach was to directly hit the endpoint in the Twitch api with a POST request (this was inspired by a comment in this thread). This approach is also not doing anything. I will include the code of that approach below.
I would much prefer to solve this problem with something built into Spring (holding out hope that there is something that I have somehow missed). An interesting thing I have been noticing happening is that when I hit /logout my browser will be redirected to Twitch's authorization endpoint which is making me think that for some reason Spring is trying to send a token revoke request to the authorization endpoint OR is logging me back into the endpoint as soon as I am logged out of it. Thought this was worth mentioning.
Any help replicating the initially mentioned behavior would be much appreciated.
SpringSecurityConfiguration:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity httpSecurity) throws Exception {
//This allows users to access the "/" and "/Info" endpoints without authenticating with Twitch. To go anywhere else they will have to authenticate.
httpSecurity.antMatcher("/**").authorizeRequests().antMatchers("/", "/Info", "/token/deletion").permitAll().anyRequest().authenticated().and().oauth2Login().and()
//This configures logout tells spring to do the logout with the method in the logoutSuccessHandler
.logout().logoutSuccessUrl("http://localhost:8080/token/deletion").invalidateHttpSession(true).clearAuthentication(true).deleteCookies("JSESSIONID", "JWT");
}
application.properties:
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
spring.security.oauth2.client.registration.twitch=twitch
spring.security.oauth2.client.registration.twitch.client-id=redacted
spring.security.oauth2.client.registration.twitch.client-secret=redacted
spring.security.oauth2.client.registration.twitch.client-authentication-method=post
spring.security.oauth2.client.registration.twitch.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.twitch.redirect-uri=http://localhost:8080/login/oauth2/code/twitch
spring.security.oauth2.client.registration.twitch.scope=user:read:email
spring.security.oauth2.client.registration.twitch.client-name=Twitch
spring.security.oauth2.client.provider.twitch.authorization-uri=https://id.twitch.tv/oauth2/authorize
spring.security.oauth2.client.provider.twitch.token-uri=https://id.twitch.tv/oauth2/token
spring.security.oauth2.client.provider.twitch.jwk-set-uri=https://id.twitch.tv/oauth2/keys
spring.security.oauth2.client.provider.twitch.user-info-uri=https://id.twitch.tv/oauth2/userinfo
spring.security.oauth2.client.provider.twitch.user-info-authentication-method=post
spring.security.oauth2.client.provider.twitch.user-name-attribute=sub
TokenRemovalController:
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.net.ssl.HttpsURLConnection;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
#Controller
public class TokenRemovalController {
#RequestMapping("/token/deletion")
public void removeTokenFromTwitch(HttpServletResponse response, #RegisteredOAuth2AuthorizedClient("twitch") OAuth2AuthorizedClient authorizedClient) throws IOException {
//Get access token of current user
String accessToken = authorizedClient.getAccessToken().getTokenValue();
//POST Request to Twitch endpoint
URL url = new URL("https://id.twitch.tv/oauth2/revoke");
HttpsURLConnection https = (HttpsURLConnection)url.openConnection();
https.setRequestMethod("POST");
https.setDoOutput(true);
https.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
String data = "client_id=redacted&token=" + accessToken;
byte[] out = data.getBytes(StandardCharsets.UTF_8);
OutputStream stream = https.getOutputStream();
stream.write(out);
String redirectString = "/error";
if (https.getResponseCode() == 200) {
redirectString = "/Info";
}
https.disconnect();
response.sendRedirect(redirectString);
}
}
Project Structure:
Another thing I forgot to mention was that if I delete all of my browsers cookies then I do get logged out of my site. Is it potentially possible to replicate this effect when users attempt to log out (obviously without deleting all of the users other cookies)?
I'm trying to add single sign on to two legacy systems on different domains. That currently have working "regular" login.
I found this https://stackoverflow.com/a/9925146 but I'm unsure about the step 1 more specifically this
"implement functionality to serialize and write the Authentication object to a Session cookie with a global scope."
If I understand this correctly I should extract the sessionID and add it to a new cookie with a global scope.
I started by trying to extract the sessionID like so
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
#Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) throws IOException,ServletException {
Cookie cookie = null;
UsernamePasswordAuthenticationToken auth = (UsernamePasswordAuthenticationToken) authentication;
if (authentication.getDetails() != null) {
WebAuthenticationDetails dets = (WebAuthenticationDetails) auth.getDetails();
System.out.println("sessionID: " + dets.getSessionId());
}
response.addCookie(cookie);
super.onAuthenticationSuccess(request,response,authentication);
}
}
To verify that I'm on the right track i print the sessionID to terminal and compare it to the sessionID that spring-security sets in the browser. If I understand correctly they should match. They don't match. Am I misunderstanding the solution suggested in the answer?
Single sign on is a very difficult problem to get right. I really would not recommend attempting to implement it unless you have a good grasp of the problem and how to solve it. If you can I highly recommend you try to use Oauth2 instead of implementing it yourself.
https://www.baeldung.com/sso-spring-security-oauth2 might give you a starting point.
If you are using an application server like JBoss or WebSphere you may be able to use their SSO option instead.
I have had a webhook listener in my Java program for a while now, and it works like it's supposed to when you send a webhook to the listener's URL. Now I need to make the URL HTTPS, but I don't know if this is a problem that I need to fix in my Java code or my Apache webserver. I have a valid trusted certificate, but whenever I try to send a webhook through Stripe, it only says TLS error and returns nothing. I think it is because the ports of the listeners aren't using SSL, but I don't know how to fix that. If I add the port to virtual hosts in Apache to use HTTPS for the port, then Java can't listen on it because it will already be in use. This is my class for the listener. Do I need to add some code for it to listen through HTTPS?
An example URL for the listener (that works) would be http://verifus.ddns.net:4568/webhook. When HTTPS is there, it doesn't work at all.
import com.stripe.Stripe;
import com.stripe.model.*;
import com.stripe.net.ApiResource;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.entities.Role;
import org.apache.commons.httpclient.HttpStatus;
import org.simplejavamail.email.Email;
import org.simplejavamail.email.EmailBuilder;
import org.simplejavamail.mailer.MailerBuilder;
import us.verif.bot.Config;
import us.verif.bot.sql.StripeSql;
import java.security.SecureRandom;
import java.util.EventListener;
import java.util.Random;
import static spark.Spark.port;
import static spark.Spark.post;
public class StripeWebhook implements EventListener {
static final private String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
final private Random rng = new SecureRandom();
private JDA jda;
public StripeWebhook(JDA jda) {
this.jda = jda;
}
public void startListener() {
port(Integer.parseInt(Config.getStripeWebhookPort()));
post("/webhook", (request, response) -> {
Event event = ApiResource.GSON.fromJson(request.body(), Event.class);
//Just some event checkers onwards
You need to configure your Apache server with your SSL certificetes. You can read the docs or follow some guides and how-tos on the exact steps.
I have a web service running on tomcat 8.5, however whenever I try to update the version, the new methods do not map properly, and 404 as a result.
For example, if a prior version had a method such as host/ContextPath/HelloWorld/, that'd run completely fine, no issues there.
However if I were to add a new method, host/ContextPath/AnotherMethod/, this method would 404.
It's not a case of the newer versions aren't being run on Azure, as you can look at the deployment history and see that it's pulling the latest versions from github, and apparently deploys them successfully.
I am unsure of how to progress from here, as what I have should be working, eg the new versions are on the server, server is running and healthy etc, yet it isn't.
Additionally, by viewing what files are on the server through site\wwwroot[project files], I can actually see that the most up to date versions of the files are on the server.
However, the methods are not being exposed, so I am at a loss as to what is happening.
For example, consider the AdministrationService, which you can see the code for below:
package services;
import controllers.DatabaseController;
import controllers.EmailController;
import controllers.ProgrammeController;
import entities.Programme;
import java.io.InputStream;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonException;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import static javax.ws.rs.HttpMethod.POST;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import utilities.SQLQuery;
#Path("/Admin")
public class AdministrationService {
ProgrammeController pc = new ProgrammeController();
/**
* A simple method for testing if our service is online.
* -> GET /API/Admin/Health
* If true is returned, we will have configured our service properly.
* #return
*/
#GET
#Path("/Health")
public Boolean getHealthy(){
return true;
}
#GET
#Path("/TestEmail")
public void testEmail(#QueryParam("target")String target){
EmailController ec = EmailController.getInstance();
String messageBody = "Hello world";
String recipient = target;
String messageSubject = "Test email";
ec.sendEmail(recipient, messageBody, messageSubject);
}
}
The /Health method is an old method. It runs just fine if I access it through
myazurehost.net/ContextPath/Admin/Health
However if I attempt to do the same with
myazurehost.net/ContextPath/Admin/TestEmail?target=testemail#gmail.com
I receive a 404 error. It's not a case of the method being incorrectly called, as the error is a 404, not a 400 bad request, 405 wrong type etc. As far as the server is concerned, the method does not exist and it's baffling.
I've tried server reboots, reinitialising the project, to no avail. Any help is greatly appreciated.
Hi,
Currently I'm using Broadleaf Commerce 2.2.0 and want to integrate paypal. I have gone through the documentation of broadleaf commerce for paypal setup (http://docs.broadleafcommerce.org/2.2/PayPal-Environment-Setup.html).
I have created paypal sanbox account also and provided the link in broadleaf as its mention, but when I'm clicking on paypal image its not redirecting to "/payapl/checkout page"
I'll get the below error in browser
HTTP ERROR 404
Problem accessing /paypal/checkout. Reason:
Not Found
and when i see my eclipse console I'll find the following error.
[ WARN] 12:12:17 PageNotFound - No mapping found for HTTP request with
URI [/paypal/checkout] in DispatcherServlet with name 'marketplace'
Is anyone know why i'm getting this error???
Thanks & Regards,
Ankit Aggarwal
I try do follow the same documentation and also configure paypal advance configration and now i'm able to access paypal getway.
Its little tricky here in fact i spent couple of hr. to understand the error which i was getting in browser finally i came to know its due to some packages which i was unable to call under my new paypal controller class. :P
So your controller class will look like this
package com.mycompany.controller.paypal;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.broadleafcommerce.core.checkout.service.exception.CheckoutException;
import org.broadleafcommerce.core.payment.service.exception.PaymentException;
import org.broadleafcommerce.core.pricing.service.exception.PricingException;
import org.broadleafcommerce.vendor.paypal.web.controller.BroadleafPayPalController;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
#Controller
public class PayPalController extends BroadleafPayPalController
{
#RequestMapping({"/paypal/checkout"})
public String paypalCheckout(HttpServletRequest request)
throws PaymentException
{
return super.paypalCheckout(request);
}
#RequestMapping({"/paypal/process"})
public String paypalProcess(HttpServletRequest request, HttpServletResponse response, Model model, #RequestParam String token, #RequestParam("PayerID") String payerID)
throws CheckoutException, PricingException
{
return super.paypalProcess(request, response, model, token, payerID);
}
}
Previously i was now importing all the packages and i was getting same issue with paypal which you are getting. once i import all the packages its works like a charm for me.
Now please check and let me know if you got any error while doing so?
Regards,
Ankit Patni