I am trying to get all the groups a user belongs to. When i run the below code i get 405 error. Am i not calling the resources correctly? Was following: https://msdn.microsoft.com/en-us/library/azure/ad/graph/api/users-operations#GetUsersMemberships
#RequestMapping(value="/groups", method = { RequestMethod.GET, RequestMethod.POST })
public JSONArray getMembersOf(HttpServletRequest httpRequest) {
try {
HttpSession session = httpRequest.getSession();
AuthenticationResult result =
(AuthenticationResult) session.getAttribute(AuthHelper.PRINCIPAL_SESSION_NAME);
String accessToken = result.getAccessToken();
String tenant = session.getServletContext().getInitParameter("tenant");
URL url =
new URL(String.format("https://graph.windows.net/%s/users/userId#abc.onmicrosoft.com/getMemberGroups?api-version=2013-04-05",
tenant, accessToken));
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// Set the appropriate header fields in the request header.
conn.setRequestProperty("api-version", "2013-04-05");
conn.setRequestProperty("Authorization", accessToken);
conn.setRequestProperty("Accept", "application/json;odata=minimalmetadata");
String goodRespStr = HttpClientHelper.getResponseStringFromConn(conn, true);
System.out.println("REsponse is --------------->>>>> "+goodRespStr);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Error:
java.io.IOException: Server returned HTTP response code: 405 for URL: https://graph.windows.net/abc.onmicrosoft.com/users/userId#abc.onmicrosoft.com/getMemberGroups?api-version=2013-04-05
According to your code, based on my understanding, I think you want to get collection that contains the object IDs of the groups of which the user is a member which is the Azure AD REST API Get Member Groups for Users. The error code returned from server seems to means Method Not Allowed which you can refer to the section 10.4.6 405 Method Not Allowed of HTTP RFC doc.
I think the issue might be caused by using an outdated value of api-version, please using 1.6 instread of 2013-04-05 in your code and try again.
Any update, please feel free to let me know.
Related
I am trying to request data from an API.The requirements of the API are given below:
Base-URL for our API is https://api.openload.co/1 (note the 1 for
version 1 behind the /)
All requests to the API shall be HTTP/1.1 GET
Please make sure to use the API with https only.
Most requests require a API Login & API Key, you can find both in the
User Panel at the "User Settings" Tab. Response is json, structure is
as follows:
{ "status": <status-code>,
"msg": "<informational message. might vary, use the status code in your code!>",
"result": <result of the request. varies depending on the request>
}
I'm using the following method to get the json response:
private static String makeHttpRequest(URL url) throws IOException {
String jsonResponse = "";
// If the URL is null, then return early.
if (url == null) {
return jsonResponse;
}
HttpsURLConnection urlConnection = null;
InputStream inputStream = null;
try {
urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setReadTimeout(10000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.setRequestMethod("GET");
urlConnection.connect()
// If the request was successful (response code 200),
// then read the input stream and parse the response.
if (urlConnection.getResponseCode() == 200) {
inputStream = urlConnection.getInputStream();
jsonResponse = readFromStream(inputStream);
} else {
Log.e(LOG_TAG, "Error response code: " + urlConnection.getResponseCode());
}
} catch (IOException e) {
Log.e(LOG_TAG, "Problem retrieving the earthquake JSON results.", e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
// Closing the input stream could throw an IOException, which is why
// the makeHttpRequest(URL url) method signature specifies than an IOException
// could be thrown.
inputStream.close();
}
}
return jsonResponse;
}
But I'm recieveing the response code 403.
I'm using the below url to test it:
https://api.openload.co/1/account/info?login={login}&key={key}
When requesting from chrome, the response is obtained in form of a file.Could that be causing the issue as I'm expecting a json response String and the server is returning a file containing the json?
Could someone point out what I'm doing wrong as if I use the same url in chrome I'm getting the json response but can''t seem to get the response via code.
A response of 403 means you either submitted credentials improperly or you submitted invalid credentials. So, there seem to be two obvious places that could be causing your issue here.
Firstly, are you properly setting your login and key into the URL at the substitution points?
Secondly, are you sure you are a valid and active login and key?
Here I am trying to register a Data Asset from Data Lake Store in the Azure Data Catalog.
I am trying to get the authentication token for Azure Data Catalog which I will then set in header as below
request.setRequestProperty("Authorization","Bearer "+accesstoken);
Code I am using to get token
//This method sends request and gets the reponse
public static String SetRequestAndGetResponse(HttpsURLConnection request, String payload)
{
String accesstoken=null;
ExecutorService service = null;
Future<AuthenticationResult> FutureResult;
AuthenticationResult result;
AuthenticationCallback callback = null;
//Creating the credential object for DataCatalog with Client ID and Client secret picked up from the vault
ClientCredential credential = new ClientCredential("client_ID", "client_secret");
try
{
service = Executors.newFixedThreadPool(1);
AuthenticationContext context = new AuthenticationContext("https://login.windows.net/tenant_ID/oauth2/token",true,service);
/*
* getting the authentication result object using the App ID URI from Azure AD as suggested in
*
* https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-code
*/
FutureResult = context.acquireToken("App ID URI from Azure AD/login/aad", credential,null);
while(!(FutureResult.isDone()))
{}
accesstoken=FutureResult.get().getAccessToken();
//System.out.println("result "+accesstoken);
}
catch(Exception e)
{System.out.println("ex "+e.getMessage());
e.printStackTrace();}
But , I am getting exception as shown below
ex com.microsoft.aad.adal4j.AuthenticationException:
{"error_description":"AADSTS50001: The application named https://abc.onmicrosoft.com/somecode/login/aad was not found in the tenant named tenant_id.
This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant.
You might have sent your authentication request to the wrong tenant.
Trace ID: some_id
Correlation ID: some_id
Timestamp: 2017-04-06 09:57:01Z","error":"invalid_resource"}
at com.microsoft.aad.adal4j.AdalTokenRequest.executeOAuthRequestAndProcessResponse(AdalTokenRequest.java:107)
at com.microsoft.aad.adal4j.AuthenticationContext.acquireTokenCommon(AuthenticationContext.java:816)
at com.microsoft.aad.adal4j.AuthenticationContext.access$100(AuthenticationContext.java:64)
at com.microsoft.aad.adal4j.AuthenticationContext$1.call(AuthenticationContext.java:172)
at com.microsoft.aad.adal4j.AuthenticationContext$1.call(AuthenticationContext.java:161)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
***************** EDIT *******************
Thanks! But, I tried with "https://graph.windows.net" as resource URI to get token using authentication context but still server responds as unauthorized request.
By the way, I am using below snippet to create a request object.
String fullUri = String.format("https://api.azuredatacatalog.com/catalogs/"+catalogName+"/views/tables?api-version=2016-03-30");
URL url = null;
try {
//sETTING UP url connection to azure data catalog api
url = new URL(fullUri);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
System.out.println("Malformed URL Exception");
}
HttpsURLConnection request;
try {
request = (HttpsURLConnection) url.openConnection();
}
catch(Exception e){ e.printStackTrace();}
Please help me on how do I get this fixed.
Thanks.
The first parameter of AuthenticationContext.acquireToken method should be the graph resource instead of your App ID URI from Azure AD.
Please change the line of code as below:
FutureResult = context.acquireToken("https://graph.windows.net", credential, null);
For more info, see: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-devquickstarts-webapp-java
Here is what you should use:
string authorityUri = "https://login.windows.net/common/oauth2/authorize";
AuthenticationContext authContext = new AuthenticationContext(authorityUri);
Also, the resource string being passed in to the AcquireToken method should be "https://api.azuredatacatalog.com".
I am following this post: Outlook RestGettingStarted. From my Java app I am trying to get AccessToken and RefreshToken. When I made Authorization code request, it ended into following error:
Sorry, but we’re having trouble signing you in. We received a bad
request.
Additional technical information: Correlation ID:
ed838d66-5f2e-4cfb-9223-a29082ecb26f Timestamp: 2015-08-20 10:20:09Z
AADSTS90011: The 'resource' request parameter is not supported.
NOTE: URL formation is correct as per documentation.
So, I removed "resource" query parameter from my code. And redirected authorize url in browser. On user consent I got authorization code. Using this code I got AccessToken. But when I try to connect with Outlook IMAP server it failed. Java ref Link for details: Java OAuth2
But it gives me error:
[AUTHENTICATIONFAILED] OAuth authentication failed.
NOTE: I added correct scope, and user email.
Then using obtained Access Token I made Mail Rest API call to get Messages from User Inbox. It ended into following error:
HTTP response:
{"error":{"code":"MailboxNotEnabledForRESTAPI","message":"REST API is
not yet supported for this mailbox."}}
Can anyone help me for following:
What is the exact cause for: "AADSTS90011: The 'resource' request parameter is not supported" after following Outlook dev docs.
How to resolve "MailboxNotEnabledForRESTAPI" error.
Is it possible to connect using java mail APIs to Outlook IMAP server with correct AccessToken ?
I ran into this recently, but don't remember which solved it. One main issue is in the documentation in that it is varying. It will tell you to attach "resource", but that is for something else like Azure.
Here is the code I used:
First request to send:
private static final String USER_OAUTH2_AUTHORIZE_URL = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
public String getOAuthDialog(Http.Request request) {
return USER_OAUTH2_AUTHORIZE_URL
+ "?client_id=" + config.getClientId()
+ "&redirect_uri=" + getOutlookLoginRedirect(request)
+ "&response_type=code"
+ "&scope=https%3A%2F%2Foutlook.office.com%2Fmail.send%20" +
"https%3A%2F%2Foutlook.office.com%2Fmail.readwrite%20" +
"offline_access%20openid%20email%20profile"
+ "&state=" + crypto.generateSignedToken();
}
Scope was the hardest thing to figure out. I found a lot of ones that did not work. And it wasn't clear that I needed to separate them with spaces.
Then they will send you a request to your redirect url that was supplied. It will contain a code which you need to exchange for the data you requested in the scope. The redirect url that is supplied needs to be the exact same. Also you need to register the redirect url on your application portal under the Platform->Add Platform->Redirect URI->Add Url
private static final String USER_ACCESS_TOKEN_URL = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
private Map<String, String> sendOutlookUserOAuthRequest(Http.Request request, String code) {
WSClient ws = WS.client();
HttpParameters params = new HttpParameters();
params.put("client_id", config.getClientId(), true);
params.put("client_secret", config.getClientSecret(), true);
params.put("code", code, true);
params.put("redirect_uri", getOutlookLoginRedirect(request), true);
params.put("grant_type", "authorization_code");
String postParams = OAuthUtil.parametersToString(params);
WSRequest wsRequest = ws.url(USER_ACCESS_TOKEN_URL)
.setMethod("POST")
.setContentType("application/x-www-form-urlencoded")
.setBody(postParams);
WSResponse wsResponse = wsRequest.execute().get(10, TimeUnit.SECONDS);
Map<String, String> result = new HashMap<>();
if (wsResponse.getStatus() != HttpStatus.SC_OK) {
return result;
}
JsonNode node = wsResponse.asJson();
if (node.hasNonNull("access_token")) {
result.put("access_token", node.get("access_token").asText());
}
if (node.hasNonNull("refresh_token")) {
result.put("refresh_token", node.get("refresh_token").asText());
}
if (node.hasNonNull("id_token")) {
String[] tokenSplit = node.get("id_token").asText().split("\\.");
if (tokenSplit.length >= 2) {
try {
JSONObject jsonObject = new JSONObject(new String(Base64.getDecoder().decode(tokenSplit[1])));
if (jsonObject.has("name")) {
result.put("name", jsonObject.get("name").toString());
}
if (jsonObject.has("email")) {
result.put("outlookUid", jsonObject.get("email").toString());
} else if (jsonObject.has("preferred_username")) {
result.put("outlookUid", jsonObject.get("preferred_username").toString());
}
} catch (JSONException e) {
log.error("Error extracting outlookUid from id_token: ", e);
}
}
}
return result;
}
Another request that you might need is to update the refresh token:
private String getAccessTokenFromRefreshToken(User user) {
WSClient ws = WS.client();
HttpParameters params = new HttpParameters();
params.put("client_id", config.getClientId(), true);
params.put("client_secret", config.getClientSecret(), true);
params.put("grant_type", "refresh_token");
params.put("refresh_token", user.getOutlookRefreshToken());
String postParams = OAuthUtil.parametersToString(params);
WSRequest wsRequest = ws.url(USER_ACCESS_TOKEN_URL)
.setMethod("POST")
.setContentType("application/x-www-form-urlencoded")
.setBody(postParams);
WSResponse wsResponse = wsRequest.execute().get(10, TimeUnit.SECONDS);
if (wsResponse.getStatus() != HttpStatus.SC_OK) {
log.error("Failure to refresh outlook access token for user: " + user +
". Received status: " + wsResponse.getStatus() + " : " + wsResponse.getStatusText());
return null;
}
JsonNode node = wsResponse.asJson();
if (node.hasNonNull("access_token")) {
String accessToken = node.get("access_token").asText();
return accessToken;
} else {
log.error("Outlook refresh token failure, 'access_token' not present in response body: " + wsResponse.getBody());
return null;
}
}
One issue I ran into that took far longer than I would have hoped was in getting the clientId and clientSecret. This was because the language microsoft uses wasn't the most explicit. Client Id and application id are used interchangeably. The client secret is also the password that you create on the Application Portal, not to be confused with the Private Key that you can generate.
So you actually want the application_id and the password, although they refer to them as client_id and client_secret with no direct indication as to the lines drawn.
This is all assuming you have set up an application on the Outlook Application Portal. https://apps.dev.microsoft.com/
I hope this helps, although I assume you probably already solved this.
I faced the same problem with Java mail. You need to add service principals for your application on the Azure AD.
Find complete steps explained in Medium article Complete guide: Java Mail IMAP OAuth2.0 Connect Outlook | by Ritik Sharma | Dec, 2022.
I am trying to manage a user session by making an ajax request to java code repeatedly
function sendSessionKeepAliveRequest() {
$.get('${URL}/sessionKeepAlive?nd=' + new Date().getTime());
}
and java code (spring framework used) handling this request:
#RequestMapping("/sessionKeepAlive")
public String dummySessionKeepAlive(HttpServletResponse response,
HttpServletRequest request) {
PrintWriter writer = null;
try {
writer = response.getWriter();
} catch (IOException e) {
logger.error(e.getMessage());
}
if (writer != null) {
response.setContentType("application/json");
// Sending an empty JSON response.
Gson gson = new Gson();
writer.write(gson.toJson(""));
}
return null;
}
Now the issue is some times were are getting 302 Found instead of 200 OK which makes jsessionid change and session got time out.I have tested in on IE and FF and both of the browser have same behaviour.
Code is deployed on IBM websphere v7.0
Please help or any direction.Please feel free if any more inputs are required or I need to modify my question.
Kind Regards
You have encountered a so-called redirection: The url of the resource you've requested has changed. The new url is provided in the http header 'Location'.
You can either read out this location and issue another Request using this url or you can set up your response handling code to automatically follow the redirection.
Sample code:
function sendSessionKeepAliveRequest() {
$.ajax(
url: '${URL}/sessionKeepAlive?nd=' + new Date().getTime()
, statusCode: {
302: function ( jqXHR, textStatus, errorThrown ) {
var url_trg = jqXHR.getResponseHeader('Location');
$.get(url_trg);
}
}
});
Update
jquery ajax requests should handle 302 status codes automatically, so there might be some other problem. Could it possibly be a cross-domain issue ?
If the purpose is just only to alive session then no need to use GSON you can pass empty String and add one annotation
#ResposeBody
This will help you to get ajax response.
I am programming a jax-rs webservice which I want to contact from a java-program. I defined a #POST method which receives a String-array as input and is supposed to return a boolean value.
But really, how can i access this return value in java? I've been searching the web for several hours now, everybody writes example methods which return Strings or something else, but nobody shows how to access the returned value from another java program.
Here is the code from the program that contacts the #POST method:
ObjectOutputStream oos = null;
String[] login = {"XXXXXX","XXXXXXX"};
try {
login[1] = PasswordGenerator.hashPassword(login[1]);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
URL url = new URL("XXXXX/XXXXXXX/XXXXXX/users/login/1");
try {
// creates a HTTP connection
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true);
httpConn.setRequestMethod("POST");
httpConn.setRequestProperty("Boolean", "application/xml");
OutputStream outputStream = httpConn.getOutputStream();
oos = new ObjectOutputStream(outputStream);
outputStream.close();
System.out.println();
} finally {
if (oos != null) {
oos.close();
}
}
}
What I want to know is: What happens after I closed my outputStream? I mean, i started the POST method, but it is supposed to return a boolean value. Where is this value? How can I access it???
JAX-RS 2.0 has a Client API that provides you with a fluent API to retrieve the content of the response:
Client client = ClientBuilder.newClient();
Boolean result = client.target("http://localhost:8080/xxx/")
.path("user/login/1")
.request(MediaType.TEXT_PLAIN_TYPE)
.post(Entity.entity(login, MediaType.APPLICATION_XML) , Boolean.class);
But unfortunately, you'll need a custom MessageBodyWriter to convert the String[] into an XML document. Maybe you should change your server-side method (and client) to manipulate a DTO - a POJO with 2 fields, username and password - and annotated with #XmlRootElement ?
something like that:
(client-side)
Credentials credentials = new
credentials.setUsername("foo");
credentials.setUsername("hashedPwd");
Client client = ClientBuilder.newClient();
Boolean result = client.target("http://xxxxx")
.path("/user/login/1")
.request(MediaType.TEXT_PLAIN_TYPE)
.post(Entity.entity(credentials, MediaType.APPLICATION_XML) , Boolean.class);
System.out.println("Result: " + result);
(server-side)
#Path("/login/{id}")
#POST
public Boolean test(#PathParam("id") String login, Credentials credentials) {
...
}