how to instantiate verifier when using scribe for facebook authentication - java

I am testing scribe for facebook authentication. I am not receiving the oauth_verifier when authenticating against facebook - let me know if this is incorrect behavior. For facebook auth, how should I go about creating the verifier in order to create the OAuthRequest.
redirect_uri=http%3A%2F%2Flocalhost%2Foauth%2Ffacebook
Thanks

LoginServlet:
public void doGet(HttpServletRequest req, HttpServletResponse res) {
OAuthService service = new ServiceBuilder().provider(FacebookApi.class).apiKey(FACEBBOK_APP_KEY)
.apiSecret(FACEBOOK_APP_SECRET).callback(FACEBOOK_CALLBACK);
String authenticationUrl = service.getAuthorizationUrl(null);
res.sendRedirect(authenticationUrl);
}
CallbackServlet:
public void doGet(HttpServletRequest req, HttpServletResponse res) {
String code = "";
Enumeration paramEnum = req.getParameterNames();
while (paramEnum.hasMoreElements()) {
String name = (String) paramEnum.nextElement();
if (name.equals("code")) {
code = req.getParameter(name);
}
OAuthService service = new ServiceBuilder().provider(FacebookApi.class).apiKey(FACEBBOK_APP_KEY)
.apiSecret(FACEBOOK_APP_SECRET).callback(FACEBOOK_CALLBACK);
Verifier verifier = new Verifier(code);
//....
}

Related

Web application deployed not generating authorization tokens

I'm trying send using gmail api with oauth2 credentials like below
private Credential getCredentials(NetHttpTransport httpTransport) throws IOException {
// Load client secrets.
try {
Resource file = resourceLoader.getResource("classpath:credentials.json");
InputStream inputStream = file.getInputStream();
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY,
new InputStreamReader(inputStream));
// Build flow and trigger user authorization request.
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(httpTransport, JSON_FACTORY,
clientSecrets, SCOPES)
.setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
.setAccessType("offline").build();
return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
} catch (Exception exception) {
exception.printStackTrace();
LOGGER.info("Exception occured:: {}", exception.getMessage());
throw new RecordNotFoundException(exception.getMessage());
}
}
using desktop app's credentials.json file.
When I have deployed in dev server I am unable to generate access and refresh token saved file.
Could you please help me.
AuthorizationCodeInstalledApp OAuth 2.0 authorization code flow for an installed Java application that persists end-user credentials.
You cant deploy that to a server its going to open the authorization window on the server.
For a web application it looks like you should be following this Oauth
public class CalendarServletSample extends AbstractAuthorizationCodeServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// do stuff
}
#Override
protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
GenericUrl url = new GenericUrl(req.getRequestURL().toString());
url.setRawPath("/oauth2callback");
return url.build();
}
#Override
protected AuthorizationCodeFlow initializeFlow() throws IOException {
return new GoogleAuthorizationCodeFlow.Builder(
new NetHttpTransport(), JacksonFactory.getDefaultInstance(),
"[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]",
Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
DATA_STORE_FACTORY).setAccessType("offline").build();
}
#Override
protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
// return user ID
}
}
public class CalendarServletCallbackSample extends AbstractAuthorizationCodeCallbackServlet {
#Override
protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential)
throws ServletException, IOException {
resp.sendRedirect("/");
}
#Override
protected void onError(
HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse)
throws ServletException, IOException {
// handle error
}
#Override
protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
GenericUrl url = new GenericUrl(req.getRequestURL().toString());
url.setRawPath("/oauth2callback");
return url.build();
}
#Override
protected AuthorizationCodeFlow initializeFlow() throws IOException {
return new GoogleAuthorizationCodeFlow.Builder(
new NetHttpTransport(), JacksonFactory.getDefaultInstance()
"[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]",
Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
DATA_STORE_FACTORY).setAccessType("offline").build();
}
#Override
protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
// return user ID
}
}
From what I have understood from your question and comments you want to achieve the following:
With your current code send email messages from your application which already works on your local machine and now you want to do it too in a web server.
Considering that you are the only user that needs to authorise the application you can achieve what you are aiming using service accounts.
A service account works best for applications like yours where you don't need authorization from your users but rather from your account to for example send emails automatically.
These type of accounts belong to your application rather than to an individual user and can make API requests without the need to authorise through the UI. This guide from the documentation will walk you step through step on how to set up your authorization with service accounts.
Moreover, bare in mind that in order for the service account to execute requests in your name (as you need an user to send emails) you should use domain-wide authorization so that the service account can make such requests in the name of the user. Also note that you need a Google Workspace account to implement domain wide authorization (let me know if you don't have it as I can propose a workaround).

Can not get UserDetails in SecurityErrorHandler

i want to get UserDetails from HttpServletRequest when I have SessionAuthenticationException - mean that session already exist for current use, but get null
My Hadnler is
public class SecurityErrorHandler extends SimpleUrlAuthenticationFailureHandler {
private static final String FORCE_PARAMETER_NAME = "force";
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception)
throws IOException, ServletException {
//if session already exist
if (exception.getClass().isAssignableFrom(SessionAuthenticationException.class)) {
logger.debug("Session already exist");
Principal userPrincipal = request.getUserPrincipal();
}
}
}
Can anyone help me?
There is no easy way. You need to get it from Authorization header
String authHeader = request.getHeader("Authorization");
byte[] base64Token =
header.trim().substring(6).getBytes(StandardCharsets.UTF_8);
byte[] decoded = java.util.Base64.getDecoder().decode(base64Token);
String token = new String(decoded, StandardCharsets.UTF_8);
int delim = token.indexOf(":");
String userName = token.substring(0, delim);
The above code can look hacky but it is actually what spring security BasicAuthenticationConverter does. https://github.com/spring-projects/spring-security/blob/master/web/src/main/java/org/springframework/security/web/authentication/www/BasicAuthenticationConverter.java#L94

Facebook4j - This authorization code has been used

I am using Facebook4j to post something on facebook. The following code worked the first time, but now it says: "This authorization code has been used". I would assume, this would give me a new access code everytime I use this, but apperently it does not. How can I tell facebook to give me a new access token instead of the same one over and over?
public class FacebookPublisher extends HttpServlet{
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Facebook facebook = new FacebookFactory().getInstance();
facebook.setOAuthAppId("appId", "appSecret");
facebook.setOAuthPermissions("email,manage_pages,publish_pages,publish_actions");
request.getSession().setAttribute("facebook", facebook);
StringBuffer callbackURL = request.getRequestURL();
int index = callbackURL.lastIndexOf("/");
callbackURL.replace(index, callbackURL.length(), "").append("/fb1callback");
response.sendRedirect(facebook.getOAuthAuthorizationURL(callbackURL.toString()));
}
}
This is the callback servlet and code:
public class FacebookPublisherCallback extends HttpServlet {
private static final long serialVersionUID = 6305643034487441839L;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Facebook facebook = (Facebook) request.getSession().getAttribute("facebook");
String oauthCode = request.getParameter("code");
try {
token = facebook.getOAuthAccessToken(oauthCode).getToken();
facebook = new FacebookFactory().getInstance();
facebook.setOAuthAppId("appId", "appSecret");
facebook.setOAuthPermissions("email,manage_pages,publish_pages,publish_actions");
facebook.setOAuthAccessToken(new AccessToken(token));
facebook.postStatusMessage("Hello World from Facebook4J.");
} catch (FacebookException e) {
e.printStackTrace();
}
}
}

OAuth "401: Invalid Credentials" after some period of time

I have created simple app using Google Drive API with OAuth2 authentication based on this sample plus-appengine-sample
So, I have two servlets implementations: AbstractAppEngineAuthorizationCodeServlet and AbstractAppEngineAuthorizationCodeCallbackServlet which should do all the hard work for me (oauth work flow).
public class DriveServlet extends AbstractAppEngineAuthorizationCodeServlet {
private static final String MY_APP_NAME = "Drive API demo";
private static final long serialVersionUID = 1L;
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
AuthorizationCodeFlow authFlow = initializeFlow();
Credential credential = authFlow.loadCredential(getUserId(req));
if (credential == null) {
resp.sendRedirect(authFlow.newAuthorizationUrl()
.setRedirectUri(OAuthUtils.getRedirectUri(req)).build());
return;
}
Drive drive = new Drive.Builder(OAuthUtils.HTTP_TRANSPORT_REQUEST,
OAuthUtils.JSON_FACTORY, credential).setApplicationName(MY_APP_NAME).build();
// API calls (examines drive structure)
DriveMiner miner = new DriveMiner(drive);
req.setAttribute("miner", miner);
RequestDispatcher view = req.getRequestDispatcher("/Drive.jsp");
view.forward(req, resp);
}
#Override
protected AuthorizationCodeFlow initializeFlow() throws ServletException, IOException {
return OAuthUtils.initializeFlow();
}
#Override
protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
return OAuthUtils.getRedirectUri(req);
}
}
public class OAuthCallbackServlet extends AbstractAppEngineAuthorizationCodeCallbackServlet {
private static final long serialVersionUID = 1L;
#Override
protected AuthorizationCodeFlow initializeFlow() throws ServletException, IOException {
return OAuthUtils.initializeFlow();
}
#Override
protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
return OAuthUtils.getRedirectUri(req);
}
#Override
protected void onSuccess(HttpServletRequest req, HttpServletResponse resp,
Credential credential) throws ServletException, IOException {
resp.sendRedirect(OAuthUtils.MAIN_SERVLET_PATH);
}
#Override
protected void onError(HttpServletRequest req, HttpServletResponse resp,
AuthorizationCodeResponseUrl errorResponse) throws ServletException, IOException {
String nickname = UserServiceFactory.getUserService().getCurrentUser().getNickname();
resp.getWriter().print(
"<h3>I am sorry" + nickname+ ", an internal server error occured. Try it later.</h1>");
resp.setStatus(500);
resp.addHeader("Content-Type", "text/html");
return;
}
}
public class OAuthUtils {
private static final String CLIENT_SECRETS_FILE_PATH = "/client_secrets.json";
static final JacksonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
static final UrlFetchTransport HTTP_TRANSPORT_REQUEST = new UrlFetchTransport();
private static final Set<String> PERMISSION_SCOPES = Collections.singleton(DriveScopes.DRIVE_READONLY);
private static final AppEngineDataStoreFactory DATA_STORE_FACTORY = AppEngineDataStoreFactory.getDefaultInstance();
private static final String AUTH_CALLBACK_SERVLET_PATH = "/oauth2callback";
static final String MAIN_SERVLET_PATH = "/drive";
private static GoogleClientSecrets clientSecrets = null;
private OAuthUtils() {}
private static GoogleClientSecrets getClientSecrets() throws IOException {
if (clientSecrets == null) {
InputStream jsonStream = OAuthUtils.class.getResourceAsStream(CLIENT_SECRETS_FILE_PATH);
InputStreamReader jsonReader = new InputStreamReader(jsonStream);
clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, jsonReader);
}
return clientSecrets;
}
static GoogleAuthorizationCodeFlow initializeFlow() throws IOException {
return new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT_REQUEST,
JSON_FACTORY, getClientSecrets(), PERMISSION_SCOPES)
.setDataStoreFactory(DATA_STORE_FACTORY)
.setAccessType("offline").build();
}
static String getRedirectUri(HttpServletRequest req) {
GenericUrl requestUrl = new GenericUrl(req.getRequestURL().toString());
requestUrl.setRawPath(AUTH_CALLBACK_SERVLET_PATH);
return requestUrl.build();
}
}
Authentication flow works as expected as well as Drive API calls, but somehow, after some period of time, I'm getting this exception on refresh:
Uncaught exception from servlet
com.google.api.client.googleapis.json.GoogleJsonResponseException: 401
{
"code" : 401,
"errors" : [{ "domain" : "global",
"location" : "Authorization",
"locationType" : "header",
"message" : "Invalid Credentials",
"reason" : "authError" }],
"message" : "Invalid Credentials"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:145)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:312)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1049)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
at sk.ennova.teamscom.drive.DriveMiner.getRootFolderId(DriveMiner.java:46)
at org.apache.jsp.Drive_jsp._jspService(Drive_jsp.java:61)
It seems that token has expired, but isn't it a work for servlets to request a new access token with the refresh token which they stored? I use offline access type, so refresh token should be delivered to callback servlet at first request.
Here "401 Unauthorized" when trying to watch changes on Google Drive with Java API Client are some hints where could be the problem, but handling token expiration should not be my case if I'm using these servlets (correct me if I am wrong). Also scope DriveScopes.DRIVE_READONLY seems OK for reading "drive" tree structure (get files of given folder and so on). Where could be the problem?
You need to first specify that you need a refresh token for offline / long term access and then save the refresh token for later use when the access token expires. You can request a new access token using the refresh token until the user revokes your access to her account. See the official documentation here:
https://developers.google.com/accounts/docs/OAuth2WebServer#refresh

What's mean the MonitorRequestWrapper and why am I not getting parameters from request?

I am working in Netbeans IDE and i have wrote JS-code for sending HTTP Request to server:
function applyFilter(){
idFilterJS = getRadioValue();
var url = "applyfilter?action=applyfilterXML&id=" + idFilterJS;
req = initRequest();
req.open("GET", url, true);
req.onreadystatechange = applyFilterCallBack;
req.send(null);
}
Next, I had a breakpoint in ApplyFilterServlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
session = request.getSession();
String action = request.getParameter("action");
}
I have two questions:
What does MonitorRequestWraper mean for request variable during debug mode?
"request.getParameter("action");" returns null. Why?
Thanks!
It extends the request. Dig down into the attributes under "inherited" to find your attributes.
public class MonitorRequestWrapper extends HttpServletRequestWrapper

Categories

Resources