I am using Postman currently to generate Bearer Token, which I am using in my automated tests. Now I would like to automate also the Bearer Token generation process too using REST Assured in Java. Please help me. Thanks.
Response response =
given()
.auth()
.oauth(
"n0pCrq5SPgraZ3CyY0Nd",
"xvvx-LVd5dszLi9OO_1qjbU4eUQ4dXwLrDZN7oioSITr_EXrgsyyOvPvZmv85Ew2",
"",
"",
"HMAC-SHA256")
.when()
.get(url)
.then()
.contentType(ContentType.JSON)
.extract()
.response();
This is working. Thanks #wilfred clement.
public static String getOauthToken(String consumerKey, String consumerSecret, String endpoint ) {
log.info("GET ACCESS TOKEN=" + endpoint);
URI uri = null;
try {
uri = new URI(endpoint);
} catch (URISyntaxException e) {
log.error("Not proper oauth url=" + endpoint);
throw new RuntimeException(e);
}
ValidatableResponse res = given()
.header("Content-Type", "application/json")
.auth().oauth(consumerKey,
consumerSecret,
"",
"")
.body("{\"grantType\": \"client_credentials\"}").when().post(uri).then();
int responseCode = res.extract().statusCode();
if (HttpURLConnection.HTTP_OK == responseCode) {
String token = res.extract().jsonPath().get("accessToken").toString();
log.info("Auth token=" + token);
return token;
} else {
String msg = "Access token retrieve failed. Http response code=" + responseCode;
log.error(msg);
throw new RuntimeException(msg);
}
}
Related
I'm getting the error: Exception: org.springframework.web.client.HttpClientErrorException$Unauthorized: 401, when trying to connect to Jira through HttpHeader, and the credentials are configured in a configserver file, which would be this:
#Component
public class JiraHttpHeadersHelper {
#Value("${first.jira.auth.user}")
private String firstJiraAuthUser;
#Value("${first.jira.auth.psw}")
private String firstJiraAuthPsw;
public HttpHeaders jiraHeadersWithAuthentication() {
String plainCreds = firstJiraAuthUser + ":" + firstJiraAuthPsw;
System.out.println("Credenciales JiraServices: "+plainCreds);
byte[] base64CredsBytes = Base64.getEncoder().encode(plainCreds.getBytes());
String base64Creds = new String(base64CredsBytes);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic" + base64Creds);
headers.setContentType(MediaType.APPLICATION_JSON);
System.out.println("Authorization JiraServices: "+headers);
return headers;
}
}
And the method where I command to call the file above and where I get the error on the line ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.GET,this.requestEnt, String.class);, would be this:
public ResponseEntity<String> getPriorityJira() {
//Request entity created
this.requestEnt = new HttpEntity(this.jiraHttpHeadersHelper.jiraHeadersWithAuthentication());
String jql = "priority";
String url = jiraBaseURL + jql;
try {
ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.GET,this.requestEnt, String.class);
System.out.println("HttpStatus"+HttpStatus.OK);
if (result.getStatusCode() == HttpStatus.OK) {
return result;
} else {
logger.error("Jira Generic User maybe blocked, status from API: " +result.getStatusCode() + ". Body: "+ result.getBody());
return new ResponseEntity<>(result.getBody(), result.getStatusCode());
}
} catch(HttpClientErrorException e) {
logger.error("Error getting priorityJira. Exception: "+ e);
return new ResponseEntity<>(e.getStatusCode());
}
}
In fact, when I run the debug and check the credentials, it brings them up without a problem. I've already searched, tried most of the links on this page and I can't find the solution.
Any help would be appreciated in this case, thanks in advance.
When you define your authorization header you concat your key with « Basic » without adding a white space.
headers.add("Authorization", "Basic" + base64Creds);
Instead of :
headers.add("Authorization", "Basic " + base64Creds);
Maybe it’s just that.
Edit :
The answer was to add StandardCharsets.UTF-8 to the String constructor.
I'm trying to make a request to the Third-party API, but I'm running into some issues using OkHTTP.
I'm using AWS4Signer to sign the request. I'm able to generate the credentials for the same.
Request<Void> requestAws = new DefaultRequest<Void>("sts");
requestAws.setHttpMethod(HttpMethodName.POST);
requestAws.setEndpoint(URI.create("third pary api call which uses https"));
requestAws.addHeader("x-amz-security-token", sessionCredentials.getSessionToken());
requestAws.addHeader("Content-Type", "application/json");
//sign the request
AWS4Signer signer = new AWS4Signer();
signer.setServiceName(Constant.SERVICE_NAME);
signer.setRegionName(Constant.AWS_REGION);
signer.sign(requestAws, new AWSCredentials() {
#Override
public String getAWSSecretKey() {
return sessionCredentials.getAccessKeyId();
}
#Override
public String getAWSAccessKeyId() {
return sessionCredentials.getSecretAccessKey();
}
});
Map<String, String> headers = requestAws.getHeaders();
String x_date = null;
String x_token = null;
String authorization = null;
String x_content = null;
//get and assign values
for (Map.Entry<String, String> entry : headers.entrySet()) {
if (entry.getKey().equals("x-amz-security-token")) {
x_token = entry.getValue();
}
if (entry.getKey().equals("X-Amz-Date")) {
x_date = entry.getValue();
}
if (entry.getKey().equals("Authorization")) {
authorization = entry.getValue();
}
}
logger.info("Headers body response: " + JsonUtils.jsonize(headers));
String json = objectMapper.writeValueAsString(emailRequestBody);
postHandler.post(x_date, x_token, authorization, json);
Below is the request code of okHTTP
String post(String x_date, String x_token, String authorization, String json) throws IOException {
RequestBody body = RequestBody.create(json, JSON);
Request request = new Request.Builder()
.url("https url is here")
.addHeader("Content-Type", "application/json")
.addHeader("X-Amz-Date", x_date)
.addHeader("x-amz-security-token", x_token)
.addHeader("Authorization", authorization)
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
Below is how the request looks like with headers:
Request{method=POST, url=https://cbc.com/api/send/email, headers=[Content-Type:application/json, X-Amz-Date:20220125T111056Z, x-amz-security-token:FwoGZXIvYXdzEHUaDF6/kQ0g7Mog7W1f7CK0ATG5xhFIXP34wRjziAkJKhw9vE5cbADBOpji7uqtLp5GLGLay+e9O2deFRB4eSpUMOOThDCEQg1tum43iX4a+8Kikuc3fv5gDjbMrdLJYAK3piYVbOAET8BAXdDdkPZVG+nNu31cEWZe9HC60svIj0m95YZ9Xx5rBIDm0AVWtj4JRCmonNm1ymCNRB4GTjhEzgnxlkqEYfdUivFdlORq/IlIssUzzV04fkr0kiqDiE9GrmU51ijAtb+PBjIt9MWbM8+x4z+y+IV4JFjuK4zrVW3Iaw4xUG/C+mpcCrZrunh+8fWgVTR6In1r, Authorization:AWS4-HMAC-SHA256 Credential=medS2y7xvISbOf7ke3IWthyCMV5koeTDD5r3gkxJ/20220125/us-west-2/execute-api/aws4_request, SignedHeaders=content-type;host;x-amz-date;x-amz-security-token, Signature=d862c9ed8175770244e17fd3cb216c2a92138183ad427ed67fc5f284a1a75266]}
Below is the response:
Response{protocol=h2, code=403, message=, url=https://cbc.com/api/send/email}
Why the response is returning 403? Can someone help me what I missed? Thank you for your time.
I am trying to run my autotests with serenity and rest-assured, but the token is not included in my request generation method. The method of getting the token itself works correctly. tell me what could be the reason.
public class ApiSteps {
private String token;
public String getAccessToken() {
RequestSpecification requestSpec = RestAssured.with();
requestSpec.given().contentType("application/x-www-form-urlencoded");
Response giveToken = RestAssured.given()
.formParam("username", "user")
.formParam("password", "pass")
.request().post("https://test.com/token");
DocumentContext doc = JsonPath.parse(giveToken.asString());
token = doc.read("access_token");
System.out.println(token);
return token;
}
final RequestSpecification spec = new RequestSpecBuilder()
.setBaseUri("https://test.com/api/v1")
.addHeader("Content-Type","application/json")
.addHeader("Accept", "text/plain")
.addHeader("Authorization", "Bearer " + getAccessToken())
.build();
#Step
public void testRest() {
given()
.spec(spec)
.when()
.get("/Test")
.then()
.assertThat()
.statusCode(200);
}
}
when starting a test in a request - null. I tried to mark with the annotation #Before, but the result is the same
You need to move the method for getting the token into a separate class and use it as follows:
NameClass nameClass = new NameClass();
.addHeader("Authorization", "Bearer " + getAccessToken())
and here use the method of this class:
nameClass.getAccessToken()
Im having an issue where I have a good oauth token with bearer type but whenever I try to make an api call it throws me a 403 Forbidden message. The call is to just get the posts from a sub reddit page(i.e. https://www.reddit.com/r/gaming.json) but with the oauth base url. Not sure if I'm missing header I need or something. Someone please help.
ServiceGenerator:
public class ServiceGenerator {
private static final String OAUTH_BASE_URL = "https://oauth.reddit.com/";
private static final String CLIENT_ID = "XXXXXXX";
private static OkHttpClient.Builder httpClient;
private static Retrofit.Builder builder;
public static <S> S createService(Class<S> serviceClass, final Context context) {
httpClient = new OkHttpClient.Builder();
builder = new Retrofit.Builder()
.baseUrl(OAUTH_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
final String token_type = PreferenceManager.getDefaultSharedPreferences(context).getString("token_type", "");
final String refresh_token = PreferenceManager.getDefaultSharedPreferences(context).getString("refresh_token", "");
final String access_token = PreferenceManager.getDefaultSharedPreferences(context).getString("access_token", "");
if(!access_token.equals("")) {
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
Log.d(TAG, "Intercepting request: " + request.url());
if(response.header("No-Authentication") == null){
response = response.newBuilder()
.addHeader("User-Agent", "my user agent")
.addHeader("Authorization", token_type + " " + access_token)
.build();
}
return response;
}
});
httpClient.authenticator(new Authenticator() {
#Override
public Request authenticate(Route route, Response response) throws IOException {
if(responseCount(response) >= 2) {
// If both the original call and the call with refreshed token failed,
// it will probably keep failing, so don't try again.
return null;
}
Log.d(TAG, "Refreshing Token");
String credentials = CLIENT_ID + ":";
String encodedCredentials = Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
// We need a new client, since we don't want to make another call using our client with access token
RedditService tokenClient = createService(RedditService.class);
Call<AccessToken> call = tokenClient.refreshToken("Basic " + encodedCredentials, "refresh_token", refresh_token);
try {
retrofit2.Response<AccessToken> tokenResponse = call.execute();
if(tokenResponse.code() == 200) {
AccessToken newToken = tokenResponse.body();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit().putBoolean("logged_in", true).apply();
prefs.edit().putString("token_type", newToken.token_type).apply();
prefs.edit().putString("access_token", newToken.access_token).apply();
prefs.edit().putString("refresh_token", newToken.refresh_token).apply();
return response.request().newBuilder()
.header("Authorization", newToken.token_type + " " + newToken.access_token)
.build();
} else {
return null;
}
} catch(IOException e) {
return null;
}
}
});
}
OkHttpClient client = httpClient.build();
Retrofit retrofit = builder.client(client).build();
return retrofit.create(serviceClass);
}
private static int responseCount(Response response) {
int result = 1;
while ((response = response.priorResponse()) != null) {
result++;
}
return result;
}
}
Client (tried with and without .json):
public interface RedditService {
#FormUrlEncoded
#POST("api/v1/access_token")
#Headers("No-Authentication: true")
Call<AccessToken> getLoginToken(#Header("Authorization") String authorization,
#Field("grant_type") String grant_type,
#Field("code") String code,
#Field("redirect_uri") String redirect_uri);
#FormUrlEncoded
#POST("api/v1/access_token")
#Headers("No-Authentication: true")
Call<AccessToken> refreshToken(#Header("Authorization") String authorization,
#Field("grant_type") String grant_type,
#Field("refresh_token") String redirect_uri);
#GET("/r/{subreddit}/{sort}")
Call<Page> getSubredditPage(#Path("subreddit") String subreddit,
#Path("sort") String sort,
#Query("after") String after);
}
EDIT:
Here's the headers that are being sent along with the request
Content-Type: text/html
Cache-Control: no-cache
Transfer-Encoding: chunked
Accept-Ranges: bytes
Date: Fri, 25 Nov 2016 20:58:55 GMT
Via: 1.1 varnish
Connection: keep-alive
X-Served-By: cache-ord1733-ORD
X-Cache: MISS
X-Cache-Hits: 0
X-Timer: S1480107535.759884,VS0,VE19
Set-Cookie: loid=omeUS2oZLIDWukuAYK; Domain=reddit.com; Max-Age=63071999; Path=/; secure
Set-Cookie: loidcreated=1480107535000; Domain=reddit.com; Max-Age=63071999; Path=/; secure
Server: snooserv
Authorization: bearer XXXXXXXXXXXXXXX
User-Agent: my-user-agent
I'm building a rest API using Spring security Oauth2 to secure it.
The following curl command runs succesfully and I get the token:
curl -X POST -vu clientapp:123456 http://localhost:8080/dms-application-0.0.1-SNAPSHOT/oauth/token -H "Accept: application/json" -d "password=spring&username=roy&grant_type=password&scope=read%20write&client_secret=123456&client_id=clientapp"
The following test to get the token also runs succesfully:
#Test
public void getAccessToken() throws Exception {
String authorization = "Basic " + new String(Base64Utils.encode("clientapp:123456".getBytes()));
String contentType = MediaType.APPLICATION_JSON + ";charset=UTF-8";
// #formatter:off
String content = mvc
.perform(
post("/oauth/token")
.header("Authorization", authorization)
.contentType(
MediaType.APPLICATION_FORM_URLENCODED)
.param("username", "roy")
.param("password", "spring")
.param("grant_type", "password")
.param("scope", "read write")
.param("client_id", "clientapp")
.param("client_secret", "123456"))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$.access_token", is(notNullValue())))
.andExpect(jsonPath("$.token_type", is(equalTo("bearer"))))
.andExpect(jsonPath("$.refresh_token", is(notNullValue())))
.andExpect(jsonPath("$.expires_in", is(greaterThan(4000))))
.andExpect(jsonPath("$.scope", is(equalTo("read write"))))
.andReturn().getResponse().getContentAsString();
// #formatter:on
String token= content.substring(17, 53);
}
However, when calling the rest end point externally from a webapp using Spring RestTemplate gives me a http error 400.
Below the code:
#RequestMapping(value = "/authentication", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity authenticate(#RequestBody CredentialsDto credentials) {
try {
String email = credentials.getEmail();
String password = credentials.getPassword();
String tokenUrl = "http://" + env.getProperty("server.host") + ":8080" + "/dms-application-0.0.1-SNAPSHOT" + "/oauth/token";
// create request body
JSONObject request = new JSONObject();
request.put("username", "roy");
request.put("password", "spring");
request.put("grant_type","password");
request.put("scope","read write");
request.put("client_secret","123456");
request.put("client_id","clientapp");
// set headers
HttpHeaders headers = new HttpHeaders();
String authorization = "Basic " + new String(Base64Utils.encode("clientapp:123456".getBytes()));
String contentType = MediaType.APPLICATION_FORM_URLENCODED.toString();
headers.set("Authorization",authorization);
headers.set("Accept","application/json");
headers.set("Content-Type",contentType);
HttpEntity<String> entity = new HttpEntity<String>(request.toString(), headers);
// send request and parse result
ResponseEntity<String> loginResponse = restClient.exchange(tokenUrl, HttpMethod.POST, entity, String.class);
// restClient.postForEntity(tokenUrl,entity,String.class,)
if (loginResponse.getStatusCode() == HttpStatus.OK) {
//JSONObject userJson = new JSONObject(loginResponse.getBody());
String response = loginResponse.getBody();
return ResponseEntity.ok(response);
} else if (loginResponse.getStatusCode() == HttpStatus.UNAUTHORIZED) {
// nono... bad credentials
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
}
return null;
}
And the error I get:
"Missing grant type"
Any ideas of what can be wrong or any other ways to do it? Because I'm completely stuck on this.
Thank you
Try to do it like this:
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("username", "roy");
map.add("password", "spring");
map.add("grant_type", "password");
map.add("scope", "read write");
map.add("client_secret","123456");
map.add("client_id","clientapp");
HttpEntity request = new HttpEntity(map, headers);
One more thing, when you ask for a token make sure not to send a json request, but with this header:
headers.add("Content-Type", "application/x-www-form-urlencoded");