Have following URL in postman to get the access token.
https://login.microsoftonline.com/:tenant_id/oauth2/token
now writing java code to do the same thing which I am doing in postman.
here is the sample code
public class RequestTest {
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
String tenant_id = "<tenant_id>";
String keys = "<client_id>:<client_secret>";
String url = "https://login.microsoftonline.com/:" + tenant_id + "/oauth2/token";
HashMap<String, String> parameters = new HashMap<>();
parameters.put("grant_type", "client_credentials");
String form = parameters.keySet().stream().map(key -> key + "=" + URLEncoder.encode(parameters.get(key),StandardCharsets.UTF_8)).collect(Collectors.joining("&"));
String encoding = Base64.getEncoder().encodeToString(keys.getBytes());
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url))
.headers("Content-Type", "application/x-www-form-urlencoded", "Authorization", "Basic "+encoding)
.POST(BodyPublishers.ofString(form)).build();
HttpResponse<?> response = client.send(request, BodyHandlers.ofString());
System.out.println(response.statusCode() + response.body().toString());
}
}
but somehow the URL is not getting formed properly as i am seeing following error :
400{"error":"invalid_request","error_description":"AADSTS900023:
Specified tenant identifier ':tenant_id' is
neither a valid DNS name, nor a valid external domain.\r\nTrace ID:
652e1996-1863-4183-aac5-ee9a74680600\r\nCorrelation ID:
45396fd8-ee9c-423b-ae5d-3bf8885d4532\r\nTimestamp: 2021-04-15
09:24:51Z","error_codes":[900023],"timestamp":"2021-04-15
09:24:51Z","trace_id":"652e1996-1863-4183-aac5-ee9a74680600","correlation_id":"45396fd8-ee9c-423b-ae5d-3bf8885d4532","error_uri":"https://login.microsoftonline.com/error?code=900023"}
please suggest where i am missing in the code ? any references please . Thanks
The request url is wrong, just remove : from it, it should be
https://login.microsoftonline.com/" + tenant_id + "/oauth2/token
Related
We found the following example, which works:
import java.net.http.HttpClient;
:
private static final HttpClient httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1)
.connectTimeout(Duration.ofSeconds(TIMEOUT)).build();
:
public String getStuff(HashMap<String,String> params) {
HttpRequest request = HttpRequest.newBuilder().GET().uri(URI.create("https://httpbin.org/get"))
.setHeader("User-Agent", "My Agent v1.0")
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
return response.body();
}
The question is how do we get the params into the request? We could manually put them in the URI by string manipulation, but this wont work for POST.
We would expect a setParameter method similar to setHeader, but this doesnt exist (according to eclipse at least).
For now I am doing it manually thusly:
String uri = "http://Somesite.com/somepath";
if (params != null) {
uri += "?";
for (String key : params.keySet()) {
uri += "" + key + "=" + params.get(key);
}
}
HttpRequest request = HttpRequest.newBuilder().GET().uri(URI.create(uri))
.setHeader("User-Agent", agent)
.build();
Presumably for POST ill have to manually construct a body with the post params structure.
Use javax.ws.rs.core.UriBuilder
It has queryParam method.
e.g.:
UriBuilder.fromLink( Link.fromUri( "somehost" ).build() )
.path( API_SERVICES )
.queryParam( "path", path)
.queryParam( "method", method )
.build();
Ok, so I am trying to achieve facebook authentication in my application but after success user is not redirected to homepage even though location header is set.
This is my current scenario.
Front-End call:
#GetMapping(value = "/login/facebook")
public String loginFacebook() {
String facebookLoginUrl = String.valueOf(this.restTemplate.getForEntity(this.serverApi + "/login/facebook",String.class).getHeaders().get("Location"));
facebookLoginUrl = facebookLoginUrl.substring(1,facebookLoginUrl.length()-1);
System.out.println(facebookLoginUrl);
return "redirect:" + facebookLoginUrl;
}
Back-End:
#RequestMapping(value = "/login/facebook", method = RequestMethod.GET)
public String startFacebookProcess() {
this.facebookConnectionFactory = new FacebookConnectionFactory(appId,appSecret);
OAuth2Operations operations = this.facebookConnectionFactory.getOAuthOperations();
OAuth2Parameters parameters = new OAuth2Parameters();
// promeni url-a za front-enda
parameters.setRedirectUri("http://localhost:8080/login/returnFromFacebook");
parameters.setScope(this.scope);
System.out.println("In startFacebookProcess");
String url = operations.buildAuthorizeUrl(parameters);
System.out.println(url);
return "redirect:" + url;
}
After that, the user is being redirected to the official facebook login page where he allows his details to be used.
Then he performs a GET request to my Front-End with his authorization code:
#GetMapping(value = "/login/returnFromFacebook")
public ResponseEntity getFacebookData(#RequestParam("code") String authorizationCode){
System.out.println(authorizationCode);
ResponseEntity response = this.restTemplate.getForEntity(this.serverApi +
"/login/returnFromFacebook?code=" + authorizationCode, ResponseEntity.class);
if(response.getStatusCode().is2xxSuccessful()){
return response;
}
return new ResponseEntity(HttpStatus.CONFLICT);
}
My Back-End is being called and I contact facebook to fetch the user data using his authorization code. Then I return a ResponseEntity which inherited all the HttpServletResponse headers and cookies.
#RequestMapping(value = "/login/returnFromFacebook", method = RequestMethod.GET)
public ResponseEntity getDataFromFacebook(#RequestParam("code") String authorizationCode,
HttpServletResponse response) throws IOException {
// leg 2
OAuth2Operations operations = this.facebookConnectionFactory.getOAuthOperations();
AccessGrant accessGrant = operations.exchangeForAccess(authorizationCode,
"http://localhost:8080/login/returnFromFacebook",null);
// leg 3
System.out.println("code: " + authorizationCode);
Connection<Facebook> connection = this.facebookConnectionFactory.createConnection(accessGrant);
User currentUser = connection.getApi().fetchObject("me", User.class,"email,first_name,last_name");
System.out.println("Email: " + currentUser.getEmail());
if(this.appUserDAO.findUserAccountByEmail(currentUser.getEmail()) == null){
Map<String, String> facebookDetailsMap = new LinkedHashMap<>();
facebookDetailsMap.put("email",currentUser.getEmail());
facebookDetailsMap.put("name",currentUser.getFirstName() + " " + currentUser.getLastName());
this.appUserDAO.saveFacebookAccount(facebookDetailsMap);
}
// Create JWT Token
String token = JWT.create()
.withSubject(currentUser.getEmail())
.withExpiresAt(new Date(System.currentTimeMillis() + JwtProperties.EXPIRATION_TIME))
.sign(HMAC512(JwtProperties.SECRET.getBytes()));
JwtAuthenticationFilter.setJwtCookie(response,token);
System.out.println(response.getStatus() + " " + response.getHeader("set-cookie"));
response.setHeader("Location", "http://localhost:8080/");
// HttpHeaders headers = new HttpHeaders();
// headers.add(index");
return new ResponseEntity<>(HttpStatus.CREATED);
}
This is the received response header in the browser. The cookies are set and everything but user is not being redirected to Location header. :
I tried to return a String "redirect:/" from GetFacebookData(Front-End) but the response cookies and headers are not being applied. I don't know why the Location header is not working.
I fixed it by returning the 'index' template if the back-end call was sucessful but also apply the cookie header into the original response (which was to the front-end) using HttpServletResponse (this is not possible with ResponseEntity btw). With HttpServletResponse you dont have to return it to the browser, it applies everything by default. With ResponseEntity you have to return ResponseEntity Object in order to apply headers. This is how the function looks like now:
#GetMapping(value = "/login/returnFromFacebook")
public String getFacebookData(#RequestParam("code") String authorizationCode, HttpServletResponse httpServletResponse) throws IOException {
System.out.println(authorizationCode);
ResponseEntity response = this.restTemplate.getForEntity(this.serverApi +
"/login/returnFromFacebook?code=" + authorizationCode, ResponseEntity.class);
System.out.println(response.getStatusCodeValue() + " " + response.getHeaders().get("Location"));
//set cookie for original request
String jwtCookieHeader = String.valueOf(response.getHeaders().get("set-cookie"));
jwtCookieHeader = jwtCookieHeader.substring(1,jwtCookieHeader.length()-1);
httpServletResponse.setHeader("set-cookie", jwtCookieHeader);
if(response.getStatusCode().is2xxSuccessful()){
return "redirect:/";
}
return String.valueOf(new ResponseEntity(HttpStatus.CONFLICT));
}
I'm trying to use Twitter's friends list api and was successful to do so without any parameters.
However whenever I add a parameter, I would get the error "Could not authenticate you." and I have no choice but to add a cursor parameter when the friend list is too long.
The fact that I get a list of users of friends when I call the api without any parameters makes me think that authenticating the request works properly.
I have tried to change the request url to https://api.twitter.com/1.1/friends/list.json?cursor=-1 which gives me the authentication error.
I tried using both https://api.twitter.com/1.1/friends/list.json and https://api.twitter.com/1.1/friends/list.json?cursor=-1 to make oauth_signature and they both failed me.
I tried using different parameters such as screen_name or user_id and they all will give me the same error.
I even tried to add cursor: -1 header like a POST request and that didn't work either.
Right now my code looks like this
public String getFriendList() {
String baseUrl = "https://api.twitter.com/1.1/friends/list.json";
// Creates a map with all necessary headers
Map<String, String> headers = createMap();
headers.put("oauth_token", <OAuth token of user>);
String signature = createSignature("GET", baseUrl, headers, <OAuth secret of user>);
// Add oauth_signature to header
headers.put("oauth_signature", signature);
String body = sendGetRequest(baseUrl, headers);
return body;
}
public String sendGetRequest(String baseUrl, Map<String, String> parameters) throws AuthException, IOException {
try (CloseableHttpClient client = CloseableHttpClientFactory.getHttpClient()) {
HttpGet httpGet = new HttpGet(baseUrl);
if (parameters != null) {
httpGet.setHeader("Authorization", createHeader(parameters));
}
CloseableHttpResponse response = client.execute(httpGet);
if (response.getStatusLine().getStatusCode() != 200) {
LOGGER.info("GET Request Failed : " + EntityUtils.toString(response.getEntity()));
throw new Exception();
}
String responseBody = EntityUtils.toString(response.getEntity());
return responseBody;
}
}
which is the working code.
Could anyone tell me where to add parameters and what I have missed to authenticate the request?
EDIT : Added code of sendGetRequest. Making the signature and adding the header was made by following the documentations from twitter
Client client = ClientBuilder.newClient();
urlApi="https://localhost:123/demo/api/v1/rows/search?";
WebTarget webTarget = client.target(urlApi);
for (Map.Entry<String, String> entry : queryParams.entrySet()) {
webTarget.queryParam(entry.getKey(), entry.getValue());
}
webTarget.queryParam("searchConditions",webTarget.queryParam("mobileNo","+9999999999"));
Invocation.Builder builder = webTarget.request();
builder.header("id", "ABC");
String asB64 = Base64.getEncoder().encodeToString("ABC:PWD".getBytes("utf-8"));
logger.debug("Calling API "+urlApi);
builder.header("Authorization", "Basic "+asB64);
builder.header("Content-type", MediaType.APPLICATION_JSON);
response = builder.get();
responseData = response.readEntity(String.class);
System.out.println(responseData);
I am trying to do GET request with searchCondition as Key and value as {mobileNo="+919999999999"}, I am unable to get this to work.
Apart from that, how can I print the Request "Headers" along with "Query params"? Thank you in advance
I think you need to encode the value inputs, something like this:
webTarget.queryParam("searchCondition", URLEncoder.encode("{mobileNo=\"+919999999999\"}", StandardCharsets.UTF_8.toString()));
UDPATE:
Example of the rest client with Spring:
#Test
public void testStack() throws Exception {
RestTemplate rest = new RestTemplate();
String fooResourceUrl="http://localhost:8080/usersParam?";
RestTemplate restTemplate = new RestTemplate();
String parameter = "{mobileNo=\"+919999999999\"}";
ResponseEntity<String> response = restTemplate.getForEntity(fooResourceUrl + "parameter=" + URLEncoder.encode(parameter, StandardCharsets.UTF_8.toString() ), String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
And this would be the rest service:
#RequestMapping(method = RequestMethod.GET, value="/usersParam")
public User getUsersInfo(#RequestParam String parameter) throws UnsupportedEncodingException {
System.out.println(URLDecoder.decode(parameter, StandardCharsets.UTF_8.toString() ));
return null;
}
I'm writing integration tests for my Dropwizard + Liquibase + Angular application to test the REST service.
My app has basic authentication with cookies.
So I've created ClassRule:
#ClassRule
public static final DropwizardAppRule<RESTServerConfiguration> RULE =
new DropwizardAppRule<>(RESTServer.class, ResourceHelpers.resourceFilePath("serverconfig.yml"));
When I test the login method:
final Response response = RULE.client().target("http://localhost:" + RULE.getLocalPort() + "/api/users/login")
.request(MediaType.APPLICATION_JSON)
.post(Entity.json("{\"username\": \"admin\", \"password\": \"admin\"}"));
everything works fine.
But when I try to test the protected resource, e.g.:
final TestResponse response = RULE.client().target("http://localhost:" + RULE.getLocalPort() + "/api/users/getAllUsers")
.request()
.get(TestResponse.class);
it fails with 401 error.
How can I get SecurityContext or store the session somewhere?
I finally figured this thing out.
All I needed to do is to extract cookies from login request, such as:
`
String cookieValue = null;
for (Map.Entry<String, NewCookie> entry : loginResponse.getCookies().entrySet()) {
String key = entry.getKey();
if ("sessionToken".equals(key)) {
cookieValue = entry.getValue().toString();
cookieValue = cookieValue.substring(0, cookieValue.indexOf(";"));
}
}
`
and then set it as a header to the protected resource request, such as:
.header("Cookie", cookieValue)