pinnaclesports api basic auth with java - java

When trying to get account balance used api I got an exception:
IOException: Server returned HTTP response code: 401 for URL:
https://api.pinnaclesports.com/v1/client/balance
Here's the code:
public void getBalance() throws Exception{
byte[] bytes = "username:password".getBytes("UTF-8");
String encoded = Base64.encodeBase64String(bytes);
System.out.println(encoded);
URL api = new URL("https://api.pinnaclesports.com/v1/client/balance");
URLConnection apiConnection = api.openConnection();
apiConnection.addRequestProperty("Authorization", "Basic "+encoded);
BufferedReader in = new BufferedReader(new InputStreamReader(apiConnection.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}

I think your authentication is broken or not set properly. The API uses Basic Auth and a Base64 encoded username/password pair. You should read http://www.pinnaclesports.com/en/api/manual#authentication and make sure that your authorization is correct.
Here's an explanation for HTTP status code 401:
Similar to 403 Forbidden, but specifically for use when authentication
is possible but has failed or not yet been provided. The response
must include a WWW-Authenticate header field containing a challenge
applicable to the requested resource.

Try using an Authenticator, like this:
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("username", "password".toCharArray());
}
});
URL api = new URL("https://api.pinnaclesports.com/v1/client/balance");
BufferedReader in = new BufferedReader(new InputStreamReader(api.openStream()));
Or if that doesn't work, then try using an HttpURLConnection instead of URLConnection,
like this:
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty ("Authorization", "Basic " + encoded);
You might also find this related post helpful, using Apache Commons.

Related

Microsoft Graph 401 Unauthorized with access token

Unable to get data from the the Microsoft Graph API.
private String getUserNamesFromGraph() throws Exception {
String bearerToken = "Bearer "+getAccessToken();
String url = "https://graph.microsoft.com/v1.0/users";
String returnData = null;
try {
URL apiURL = new URL(url);
URLConnection con = apiURL.openConnection();
con.setRequestProperty("Authorization", bearerToken);
con.setRequestProperty("Content-Type", "application/json");
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
returnData = response.toString();
System.out.println(returnData);
} catch(Exception e) {
System.out.println(e);
}
return returnData;
}
private String getAccessToken() throws Exception {
String url = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
// header
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "eTarget API");
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
String urlParameters = "client_id=***
APPLICATION ID FROM APPLICATION REGISTRATION PORTAL ***&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret=***
APPLICATION SECRET FROM APPLICATION REGISTRATION PORTAL ***&grant_type=client_credentials";
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + urlParameters);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
String returnData = response.toString();
System.out.println(returnData);
Map jsonTokenData = new Gson().fromJson(returnData, Map.class);
String accessToken = (String)jsonTokenData.get("access_token");
//System.out.println(accessToken);
return accessToken;
}
The application is registered
I have a method getAccessToken() that successfully returns an access token
The method getUserNamesFromGraph() however returns a 401 Unauthorized instead of the expected data.
I've gone through the documentation countless times, trying different variations and endpoints but to no avail. Any ideas appreciated.
In order your application to read the users it has to have an explicitly granted User.Read.All application permission. This permission requires admin consent. Here is one link where it is explained how to grant that permission. You must invoke that interactive consent dialog to grant your application the permissions. Otherwise you will still receive Insufficient permissions error.
Then here is the complete list of different Microsoft Graph permissions. In your case - a daemon application without user interaction, you have to look at the application permissions and not **delegated permissions*.
Once you grant appropriate permissions, you will be able to query the users. You do not have to change the scope in your token request. Leave it as it is: https://graph.microsoft.com/.default
Once you make all these changes, you can use https://jwt.ms to check your access token. There you can extract all the claims and check your audience and scope claims to further understand why you get 401 from the Microsoft Graph.
The reason for this is the application must also have support for the permissions requested. Case in point is an application isn't allowed to list managed devices as shown in the Prerequisites page in this page
List managedDevices permissions

Server returned HTTP response code: 415 Unsupported media type

I have a rest web service like below.
#POST
#Path("/startProcess")
#Produces(MediaType.TEXT_PLAIN)
#Consumes(MediaType.APPLICATION_JSON)
public String startProcess(InputParams inputParams, #Context HttpServletRequest request, #Context HttpServletResponse response) {
ProjectBean projBean = new ProjectBean();
Helper.loadProjectBean(inputParams, projBean);
return "1";
}
Now I am trying to consume it with below main program.
public static void main(String[] args) throws Exception {
StringBuffer response = new StringBuffer();
String taigaServiceUrl = "http://localhost:8181/restServer/rest/TestWebService/startProcess/";
URL url = new URL(taigaServiceUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/json");
String userpass = "admin" + ":" + "admin";
String basicAuth = "Basic " + new String(new Base64().encode(userpass.getBytes()));
conn.setRequestProperty("Authorization", basicAuth);
InputParams inputParams = new InputParams();
inputParams.setXXX("xxxx");
inputParams.setYYYY("123456");
inputParams.setZZZZ("ZZZZ");
String json = new Gson().toJson(inputParams);
DataOutputStream os = new DataOutputStream (conn.getOutputStream());
os.write(json.getBytes());
os.flush();
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
String inputLine;
while ((inputLine = br.readLine()) != null) {
response.append(inputLine);
}
br.close();
}
But every time I am getting below error.
Exception in thread "main" java.io.IOException: Server returned HTTP response code: 415 for URL: http://localhost:8181/restServer/rest/TestWebService/startProcess/
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at scm.controllers.Test.main(Test.java:64)
As per error the media type is unsupported. In my rest webservice I am consuming JSON and in my main program I am sending JSON. Then where it is breaking?
Well after lot of debugging I found solution of my problem. I needed to add below jars in classpath. Actually Jersey was not able to bind JSON object to the rest service.
jackson-annotations-2.5.4.jar
jackson-core-2.5.4.jar
jackson-databind-2.5.4.jar
jackson-jaxrs-base-2.5.4.jar
jackson-jaxrs-json-provider-2.5.4.jar
jersey-entity-filtering-2.22.2.jar
jersey-media-json-jackson-2.22.2.jar
Have a look at this guide:
I think you need to define a json processor:
https://www.nabisoft.com/tutorials/java-ee/producing-and-consuming-json-or-xml-in-java-rest-services-with-jersey-and-jackson
thanks.
This is the issue with your #Produces and #Consumes.
#Produces(MediaType.TEXT_PLAIN)
#Consumes(MediaType.APPLICATION_JSON)
As per the annotation, your endpoint receives JSON and result would be TEXT.
But in your client program, you have mentioned content type as json.
conn.setRequestProperty("Content-Type", "application/json");
Hence client expects a json, where as its not.
Change this as
conn.setRequestProperty("Content-Type", "text/plain");
would work.

Server returned HTTP response code: 401 for URL: https

I'm using Java to access a HTTPS site which returns the display in an XML format. I pass the login credentials in the URL itself. Here is the code snippet:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
requestURL = "https://Administrator:Password#localhost:8443/abcd";
try {
InputStream is = null;
URL url = new URL(requestURL);
InputStream xmlInputStream =new URL(requestURL).openConnection().getInputStream();
byte[] testByteArr = new byte[xmlInputStream.available()];
xmlInputStream.read(testByteArr);
System.out.println(new String(testByteArr));
Document doc = db.parse(xmlInputStream);
System.out.println("DOC="+doc);
} catch (MalformedURLException e) {
}
I'm creating a trust manager in the program which does not validate signed/unsigned certificates. But, on running the above program, I get the error
Server returned HTTP response code: 401 for URL: https://Administrator:Password#localhost:8443/abcd
I can use the same url on my browser and it displays the xml correctly. Kindly let me know how to make this work within the Java program.
401 means "Unauthorized", so there must be something with your credentials.
I think that java URL does not support the syntax you are showing. You could use an Authenticator instead.
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(login, password.toCharArray());
}
});
and then simply invoking the regular url, without the credentials.
The other option is to provide the credentials in a Header:
String loginPassword = login+ ":" + password;
String encoded = new sun.misc.BASE64Encoder().encode (loginPassword.getBytes());
URLConnection conn = url.openConnection();
conn.setRequestProperty ("Authorization", "Basic " + encoded);
PS: It is not recommended to use that Base64Encoder but this is only to show a quick solution. If you want to keep that solution, look for a library that does. There are plenty.
Try This. You need pass the authentication to let the server know its a valid user. You need to import these two packages and has to include a jersy jar. If you dont want to include jersy jar then import this package
import sun.misc.BASE64Encoder;
import com.sun.jersey.core.util.Base64;
import sun.net.www.protocol.http.HttpURLConnection;
and then,
String encodedAuthorizedUser = getAuthantication("username", "password");
URL url = new URL("Your Valid Jira URL");
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setRequestProperty ("Authorization", "Basic " + encodedAuthorizedUser );
public String getAuthantication(String username, String password) {
String auth = new String(Base64.encode(username + ":" + password));
return auth;
}

Java HTTP PUT with Digest authentication in Java

I am trying to upload a file with Java using PUT, server does Digest authentication. I want to keep it lean, so I try to use HttpURLConnection.
public void putData(String path, byte [] data) throws IOException, MalformedURLException {
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user,password.toCharArray());
}});
debug("Default authenticator set");
//Safeguard against double slashes
if (path.startsWith("/")) {
path = path.replaceFirst("/","");
}
debug(hostname + path);
URL url = new URL(hostname + path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
debug("HttpURLConnection acquired");
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("PUT");
conn.setRequestProperty("Content-Length",String.valueOf(data.length));
conn.setRequestProperty("Content-type","application/binary");
conn.setFixedLengthStreamingMode(data.length);
conn.connect();
debug("Properties set");
OutputStream out = conn.getOutputStream();
debug("Outputstrem acquired");
out.write(data,0,data.length);
out.flush();
out.close();
debug("Data written, stream closed.");
}
For some reason, this fails hopelessly: I see a 401 coming back, and then it's done. If I disable authorization, same code works. Downloading a file with similar code using digest authentication "just works". Any ideas? I'd really rather not start using the next so many libraries like htclient from Apache or so (...it's 2010... you'd expect http requests with digest authN to work in any standard library).
You should at least try conn.getInputStream() at the end of your method, to force evaluation of the server response. Otherwise, potential error messages from the server will not be detected properly.

Using HTTP Basic-Auth with Google App Engine URLFetch service

How can I specify the username and password for making Basic-Auth requests with App Engine's URLFetch service (in Java)?
It seems I can set HTTP headers:
URL url = new URL("http://www.example.com/comment");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("X-MyApp-Version", "2.7.3");
What are the appropriate headers for Basic-Auth?
This is a basic auth header over http:
Authorization: Basic base64 encoded(username:password)
eg:
GET /private/index.html HTTP/1.0
Host: myhost.com
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
You will need to do this:
URL url = new URL("http://www.example.com/comment");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Authorization",
"Basic "+codec.encodeBase64String(("username:password").getBytes());
And to do that you will want to get a base64 codec api, like the Apache Commons Codec
For those interested in doing this in Python (as I was), the code looks like this:
result = urlfetch.fetch("http://www.example.com/comment",
headers={"Authorization":
"Basic %s" % base64.b64encode("username:pass")})
You set up an Authenticator before you call openConnection() like this,
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
});
Since there is only one global default authenticator, this doesn't really work well when you have multiple users doing the URLFetch in multiple threads. I would use Apache HttpClient if that's the case.
EDIT: I was wrong. App Engine doesn't allow Authenticator. Even if it's allowed, we would have the multi-thread issue with a global authenticator instance. Even though you can't create threads, your requests may still get served in different threads. So we just add the header manually using this function,
import com.google.appengine.repackaged.com.google.common.util.Base64;
/**
* Preemptively set the Authorization header to use Basic Auth.
* #param connection The HTTP connection
* #param username Username
* #param password Password
*/
public static void setBasicAuth(HttpURLConnection connection,
String username, String password) {
StringBuilder buf = new StringBuilder(username);
buf.append(':');
buf.append(password);
byte[] bytes = null;
try {
bytes = buf.toString().getBytes("ISO-8859-1");
} catch (java.io.UnsupportedEncodingException uee) {
assert false;
}
String header = "Basic " + Base64.encode(bytes);
connection.setRequestProperty("Authorization", header);
}
Using HttpURLConnection gave me some problems (for some reason the server I was trying to connect to didn't accept auth credentials), and finally I realized that it's actually much easier to do using GAE's low-level URLFetch API (com.google.appengine.api.urlfetch) like so:
URL fetchurl = new URL(url);
String nameAndPassword = credentials.get("name")+":"+credentials.get("password");
String authorizationString = "Basic " + Base64.encode(nameAndPassword.getBytes());
HTTPRequest request = new HTTPRequest(fetchurl);
request.addHeader(new HTTPHeader("Authorization", authorizationString));
HTTPResponse response = URLFetchServiceFactory.getURLFetchService().fetch(request);
System.out.println(new String(response.getContent()));
This worked.
There is a wrapper on Apache HttpClient for App Engine
please go through the post http://esxx.blogspot.com/2009/06/using-apaches-httpclient-on-google-app.html
http://peterkenji.blogspot.com/2009/08/using-apache-httpclient-4-with-google.html
Note on the first answer: setRequestProperty should get the property name without the colon ("Authorization" rather than "Authorization:").

Categories