Graph API in SSO is not working in Azure AD - java

I am trying to develop a Java web application with SSO by following this azure tutorial. I created an account in Azure and created an AD. Developed and deployed the code in Tomcat. When I try to access the page, I am getting the following error
Exception - java.io.IOException: Server returned HTTP response code: 403 for URL: https://graph.windows.net/ppceses.onmicrosoft.com/users?api-version=2013-04-05
I do not find enough answers for this error. I changed the api-version to 1.6. Even then it did not work.
MORE ANALYSIS:
After troubleshooting, I found out that the logged-in user info is fetched and is available in Sessions object. It errors out when its trying to read the response and convert into the String object. Following is the calling method where it errors out.
HttpClientHelper.getResponseStringFromConn(conn, true);
Actual method to write the response into String:
public static String getResponseStringFromConn(HttpURLConnection conn, boolean isSuccess) throws IOException {
BufferedReader reader = null;
if (isSuccess) {
reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} else {
reader = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
}
StringBuffer stringBuffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
stringBuffer.append(line);
}
return stringBuffer.toString();
}
The actual issue is on the Graphic API where we try to read the response in the String format.

#Anand, According to Microsoft Graph error responses and resource types, the response code 403 means Forbidden below.
Access is denied to the requested resource. The user might not have enough permission.
Please move to the CONFIGURE tab of your application registered in your AAD domain on Azure classic portal, then check whether enable enough permission, please see the figure below.

I got the same error, been struggling with it a few days. What I noticed was that even if I checked ALL permissions for Windows Azure Active Directory I still got the 403. So, I deleted the app in App Registrations and created it again from scratch, generated new application key and readded reply urls. In Required Permissions/Windows Azure Active Directory check:
Sign in and read user profile
Access the directory as the signed-in user
I can now call me/memberOf successfully.
Hope it helps.

The below worked for me.
At the active directory app registrations -> app ->settings->permissions-> enable delegate permissions to read directory data. Save and close the blade. Also Click Grant Permissions and close the blade.
Once the above is done, Log out and Log in back with a fresh token to the application. (Guess the token with prior authorizations will not reflect the latest permission changes and hence the re-login may have worked in my case)

Related

Azure Graph API 403 Error using Java tutorial

I’ve been working through a doc at:
https://learn.microsoft.com/en-us/azure/active-directory/active-directory-devquickstarts-webapp-java
But when I run the project, I’m redirected to the ADFS login page and after authentication im receiving this error:
java.io.IOException: Server returned HTTP response code: 403 for URL: https://graph.windows.net/swisherint.onmicrosoft.com/users?api-version=2013-04-05
I get this error when I run from local host. I also deployed the sample app to Azure and getting the same error.
I've added permissions to Graph API with read directory permissions in active directory > App Registrations > Required permissions. I also added Windows Azure Active Directory permissions (sign in and read user profile)
Is this a common error? Am I using the wrong version of the Graph API? I've tried several solutions from other questions but not working.
It appears that the Azure Graph API requires the URI connection type, instead of the HttpUrlConnection the java tutorial used. This works without the 403 error:
try{
// OAuth2 is required to access this API. For more information visit:
// https://msdn.microsoft.com/en-us/office/office365/howto/common-app-authentication-tasks
// Specify values for path parameters (shown as {...})
URIBuilder builder = new URIBuilder("https://graph.windows.net/swisherint.onmicrosoft.com/users");
// Specify values for the following required parameters
builder.setParameter("api-version", "1.6");
// Specify values for optional parameters, as needed
// builder.setParameter("$filter", "startswith(displayName,'A')");
URI uri = builder.build();
HttpGet request = new HttpGet(uri);
HttpResponse response = httpclient.execute(request);
HttpEntity entity = response.getEntity();
if (entity != null) {
System.out.println(EntityUtils.toString(entity));
}
users = EntityUtils.toString(entity);
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
Thanks for responding!
KB
According to the new offical document reference for AAD Graph API Get Users, it seems the api-version property in the code should be changed to 1.6. Please try it.
Meanwhile, there is an Error code reference list that you can find the description of the common error code 403 for AAD Graph API calling. And be checking whether your issue is belong to the one of the errors Authentication_Unauthorized, Authorization_RequestDenied & Directory_QuotaExceeded.
Any update, please feel free to let me know.

Using URLConnetion.getInputStream() to get source code (amazon.de)

When I want to get the source code of a specific web page, I use following code:
URL url = new URL("https://google.de");
URLConnection urlConnect = url.openConnection();
BufferedReader br = new BufferedReader(new InputStreamReader(urlConnect.getInputStream())); //Here is the error with the amazon url
StringBuffer sb = new StringBuffer();
String line, htmlData;
while((line=br.readLine())!=null){
sb.append(line+"\n");
}
htmlData = sb.toString();
The code above works without problems, but when your url is called...
URL url = new URL("https://amazon.de");
...then you might get sometimes a IOException error -> Server error code 503. In my opinion, this doesn't make any sense, because I can enter the amazon web page with the browser without any errors.
When accessing https://amazon.de with curl -v https://amazon.de you either get a 503 or a 301 status code in the response (When following the redirect, you get a 503 from the referenced location https://www.amazon.de/). The body contains the following comment:
To discuss automated access to Amazon data please contact api-services-support#amazon.com.
For information about migrating to our APIs refer to our Marketplace APIs at https://developer.amazonservices.de/ref=rm_5_sv, or our Product Advertising API at https://partnernet.amazon.de/gp/advertising/api/detail/main.html/ref=rm_5_ac for advertising use cases.
I assume Amazon is returning this response when your request is detected as coming from a non browser context (i.e. by parsing the user agent) to hint you towards using the APIs and not crawling the sites directly.

Google DrEdit example for Java won't work

I followed the steps to deploy DrEdit for Java:
https://github.com/googledrive/dredit/tree/master/java
When I visit the app, I get this error in the AppEngine log console!
2013-10-02 12:51:08.404
/start
java.lang.NullPointerException
at com.google.drive.samples.dredit.DrEditServlet.loginIfRequired(DrEditServlet.java:149)
at com.google.drive.samples.dredit.StartPageServlet.doGet(StartPageServlet.java:46)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
This is line 149. credentialManager is null.
protected void loginIfRequired(HttpServletRequest req,
HttpServletResponse resp) {
Credential credential = getCredential(req, resp);
if (credential == null) {
// redirect to authorization url
try {
resp.sendRedirect(credentialManager.getAuthorizationUrl()); // line 149
It's supposed to be set in init()
public void init() throws ServletException {
super.init();
// init credential manager
credentialManager = new CredentialManager(
getClientSecrets(), TRANSPORT, JSON_FACTORY);
}
I was unable to use System.out.println because it would never display in the logs, even though I selected "All Requests".
I'm also getting NoSuchMethodError:
Error for /
java.lang.NoSuchMethodError: com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets.load(Lcom/google/api/client/json/JsonFactory;Ljava/io/InputStream;)Lcom/google/api/client/googleapis/auth/oauth2/GoogleClientSecrets;
at com.google.drive.samples.dredit.DrEditServlet.getClientSecrets(DrEditServlet.java:249)
at com.google.drive.samples.dredit.DrEditServlet.init(DrEditServlet.java:88)
at javax.servlet.GenericServlet.init(GenericServlet.java:212)
at org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:440)
This happens to be the line:
249 return GoogleClientSecrets.load(JSON_FACTORY, stream);
I should mention that it works ok locally when I visit localhost:8888/start, in that it just sends me to Google to authenticate, but of course fails when it tries to redirect to the appspot.com/oauth2callback.
The "NoSuchMethodError" is probably a mismatch between the code you have copy/pasted and the version of the Google Oauth library that you have installed. My guess would be that the library was updated, but Google didn't go back and update the DrEdit example. If you're using Eclipse with the Google plugin it will get the latest libs for you.
On your last point, to test oauth on your local server, there are a couple of tricks.
Option 1. Create an entry in your local /etc/hosts file (or equivalent) 127.0.0.1 dev.example.com. You can then configure dev.example.com as a callback URL in the API console.
Option 2. Use goo.gl to create a shortened URL for localhost:8000/mycallbackservlet You can then configure the shortened URL as a callback URL in the API console. (NB, I use option 1, so haven't tried this personally).
In both cases, you will need to modify your code to sense it's running on the local devserver and adjust its callback URL accordingly.
On your NPE question, clearly it's hard to say without further information, but my 2c is DrEdit is not a good entry point to understanding oauth.
hth
Currently, I am also working on DrEdit code and I have been through the error as no such method for line -
return GoogleClientSecrets.load(JSON_FACTORY, stream);
I corrected the code by adding one line before this statement as -
InputStream stream = getServletContext().getResourceAsStream(CLIENT_SECRETS_FILE_PATH);
InputStreamReader reader = new InputStreamReader(stream); //I have added this line.
try {
return GoogleClientSecrets.load(JSON_FACTORY, reader); //initially it was stream. I changed it to reader.
This solves my no such method problem. I am not sure about the NPE that you are getting. Hope this small correction, also resolves your problem.

Response code 401 when accesing rest based web services with correct credentials

I am getting Unauthorized error when accessing restful web services. My sample program looks like this.
public static void main(String[] args){
// Use apache commons-httpclient to create the request/response
HttpClient client = new HttpClient();
Credentials defaultcreds = new UsernamePasswordCredentials("aaa", "cdefg");
client.getState().setCredentials(AuthScope.ANY, defaultcreds);
GetMethod method = new GetMethod(
"http://localhost:8080/userService/usersByID/1234");
try {
client.executeMethod(method);
InputStream in = method.getResponseBodyAsStream();
// Use dom4j to parse the response and print nicely to the output stream
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder out = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
out.append(line);
}
System.out.println(out.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
My credentials are correct. My web services will consume Basic Http Authentication.
I have doubt at scope of authentication.
client.getState().setCredentials(AuthScope.ANY, defaultcreds);
My credentials are correct.
Can any one help to resolve this issue.
Thanks.
First check your url via browser and verify ?? as mentioned here
Fixing 401 errors - general
Each Web Server manages user authentication in its own way. A security officer (e.g. a Web Master) at the site typically decides which users are allowed to access the URL. This person then uses Web server software to set up those users and their passwords. So if you need to access the URL (or you forgot your user ID or password), only the security officer at that site can help you. Refer any security issues direct to them.
If you think that the URL Web page *should* be accessible to all and sundry on the Internet, then a 401 message indicates a deeper problem. The first thing you can do is check your URL via a Web browser. This browser should be running on a computer to which you have never previously identified yourself in any way, and you should avoid authentication (passwords etc.) that you have used previously. Ideally all this should be done over a completely different Internet connection to any you have used before (e.g. a different ISP dial-up connection). In short, you are trying to get the same behaviour a total stranger would get if they surfed the Internet to the Web page.
If this type of browser check indicates no authority problems, then it is possible that the Web server (or surrounding systems) have been configured to disallow certain patterns of HTTP traffic. In other words, HTTP communication from a well-known Web browser is allowed, but automated communication from other systems is rejected with an 401 error code. This is unusual, but may indicate a very defensive security policy around the Web server.
Manual Fix
Hit the url from the browser and record the HTTP traffic (Headers,body)
Run the Java client code and record the HTTP traffic (Headers,body)
Analyze and fix the differences

IOException when Uploading Videos to YouTube via Java API

I have been attempting to upload videos to YouTube via the JavaAPI using Direct Uploading. I have been having a problem when I call the insert() method, I get a IOException with the error message
"Error writing request body to the server"
I have verified that the File object I am creating is correct as well as all the details in my VideoEntry object. I have been using Fiddler to monitor the activity from my machine and no request is made to the upload API so the problem is not there. Here is a summary of the code I am using:
VideoEntry newVideo = new VideoEntry();
//Defined video properties such as title and description here.
MediaFileSource ms = new MediaFileSource(videoFile, "video/flv");
newVideo.setMediaSource(ms);
VideoEntry createdEntry = settings.insert(new URL(apiUrl), newVideo);
The IOException is thrown on the insert call (settings is my YouTubeService instance) and the API URL appears to be correct.
Prior to this I have succeeded in uploading this video using the C# API so I know the video file is valid.
--Update
This is the apiURL value:
http://uploads.gdata.youtube.com/feeds/api/users/default/uploads
Make certain that videoFile actually points to the correct local file. The File(String) constructor won't verify that it actually exists. The MediaFileSource constructor and VideoEntry.setMediaSource() method also never check that the file is valid. The error message "Error writing request body to the server" sounds like the insert method can not find the body of the message it is trying to send.
File videoFile = new File("...");
if (videoFile.exists() == false) {
System.err.println("FAIL");
}
to test if the file exists.
If you are under a firewall env and had configured your proxy settings in jvm system properties. The try configuring your youtube service as:
service.setChunkedMediaUpload(MediaService.NO_CHUNKED_MEDIA_REQUEST);
or in your case
settings.setChunkedMediaUpload(MediaService.NO_CHUNKED_MEDIA_REQUEST);
since as you say is your YouTubeService instance.
hope this helps.

Categories