Trying to download a file am getting an error, i couldn't able to download the file from Drive.
Here is the code i used
private static InputStream downloadFile(String token, File file) {
Drive service = getDriveService(getCredential(token));
if (file.getDownloadUrl() != null && file.getDownloadUrl().length() > 0) {
try {
HttpResponse resp =
service.getRequestFactory().buildGetRequest(new GenericUrl(file.getDownloadUrl()))
.execute();
return resp.getContent();
} catch (IOException e) {
// An error occurred.
e.printStackTrace();
return null;
}
} else {
// The file doesn't have any content stored on Drive.
return null;
}
}
and i'm getting this error
GET /a/thotz.net/uc?id=xxxxx&export=download HTTP/1.1
Host: docs.google.com
Content-length: 0
Authorization: OAuth ya29.AHES6ZTruwaMm_SHZAb9LFMCbxiJ85vaDccbil-h4enw
HTTP/1.1 401 Unauthorized
Content-length: 147
X-xss-protection: 1; mode=block
X-content-type-options: nosniff
X-google-cache-control: remote-fetch
-content-encoding: gzip
Server: GSE
Reason: Unauthorized
Via: HTTP/1.1 GWA
X-chromium-appcache-fallback-override: disallow-fallback
Cache-control: private, max-age=0
Date: Thu, 25 Apr 2013 19:54:12 GMT
X-frame-options: SAMEORIGIN
Content-type: text/html; charset=UTF-8
Expires: Thu, 25 Apr 2013 19:54:12 GMT
<HTML>
<HEAD>
<TITLE>Unauthorized</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Unauthorized</H1>
<H2>Error 401</H2>
</BODY>
</HTML>
i test the token in other request and is it work, so don't know why when i try to download a file show a 401 error.
I had similar problem using PHP library - turns out you need to make your request with authentication - 401 error means you are not authenticated.
Related
I am having a bit of an issue with logging my headers.
Here is my class that implements interceptor:
public class AuthInterceptor implements Interceptor {
private SessionManagement sessionManagement;
public AuthInterceptor(Context ctx) {
this.sessionManagement = new SessionManagement(ctx);
}
#NonNull
#Override
public Response intercept(#NonNull Chain chain) throws IOException {
Request request = chain.request();
Request.Builder requestBuilder = request.newBuilder();
// if token saved, add to request
String token = sessionManagement.getSessionToken();
if (token != null) {
requestBuilder.addHeader("Authorization", "Bearer " + token);
}
return chain.proceed(requestBuilder.build());
}
}
And here is my ApiClient class:
public class ApiClient {
public static final String BASE_URL = "some/url";
public static Retrofit retrofit = null;
public static Retrofit getApiClient(Context context) {
if (retrofit == null) {
Gson gson = new GsonBuilder()
.setLenient()
.create();
AuthInterceptor authInterceptor = new AuthInterceptor(context);
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
ClearableCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(context));
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(authInterceptor)
.addInterceptor(logging)
.cookieJar(cookieJar)
.build();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(okHttpClient)
.build();
}
return retrofit;
}
}
I feel these have been implemented correctly, but I am still unable to see the headers in my logs:
2023-01-26 13:35:53.361 7841-7924 okhttp.OkHttpClient com.example.releasesapp I --> POST http://.../loginuser.php
2023-01-26 13:35:53.361 7841-7924 okhttp.OkHttpClient com.example.releasesapp I Content-Type: application/json; charset=UTF-8
2023-01-26 13:35:53.361 7841-7924 okhttp.OkHttpClient com.example.releasesapp I Content-Length: 41
2023-01-26 13:35:53.361 7841-7924 okhttp.OkHttpClient com.example.releasesapp I {"email":"t#t.com","password":"test1234"}
2023-01-26 13:35:53.361 7841-7924 okhttp.OkHttpClient com.example.releasesapp I --> END POST (41-byte body)
2023-01-26 13:35:53.458 7841-7924 okhttp.OkHttpClient com.example.releasesapp I <-- 200 OK http://.../loginuser.php (96ms)
2023-01-26 13:35:53.458 7841-7924 okhttp.OkHttpClient com.example.releasesapp I Date: Thu, 26 Jan 2023 12:35:54 GMT
2023-01-26 13:35:53.458 7841-7924 okhttp.OkHttpClient com.example.releasesapp I Server: Apache/2.4.54 (Win64) OpenSSL/1.1.1p PHP/8.1.10
2023-01-26 13:35:53.458 7841-7924 okhttp.OkHttpClient com.example.releasesapp I X-Powered-By: PHP/8.1.10
2023-01-26 13:35:53.458 7841-7924 okhttp.OkHttpClient com.example.releasesapp I Expires: Thu, 19 Nov 1981 08:52:00 GMT
2023-01-26 13:35:53.458 7841-7924 okhttp.OkHttpClient com.example.releasesapp I Cache-Control: no-store, no-cache, must-revalidate
2023-01-26 13:35:53.458 7841-7924 okhttp.OkHttpClient com.example.releasesapp I Pragma: no-cache
2023-01-26 13:35:53.458 7841-7924 okhttp.OkHttpClient com.example.releasesapp I Set-Cookie: PHPSESSID=l08iqa7cs8tvt1bfnijkl1r7d8; path=/
2023-01-26 13:35:53.459 7841-7924 okhttp.OkHttpClient com.example.releasesapp I Content-Length: 194
2023-01-26 13:35:53.459 7841-7924 okhttp.OkHttpClient com.example.releasesapp I Keep-Alive: timeout=5, max=100
2023-01-26 13:35:53.459 7841-7924 okhttp.OkHttpClient com.example.releasesapp I Connection: Keep-Alive
2023-01-26 13:35:53.459 7841-7924 okhttp.OkHttpClient com.example.releasesapp I Content-Type: text/html; charset=UTF-8
2023-01-26 13:35:53.459 7841-7924 okhttp.OkHttpClient com.example.releasesapp I {"status_code":200,"auth_token":"TEMPTOKEN","user":{"id":"30","full_name":null,"username":"t","password_hash":"$2y","email":"t#t.com"}}
2023-01-26 13:35:53.459 7841-7924 okhttp.OkHttpClient com.example.releasesapp I <-- END HTTP (194-byte body)
Additionally, if I completely comment out my OkHttpClient (as well as the .client(okHttpClient) line), my log still shows okhttpclient. Is this normal?
Appreciate any help I can get with this.
try this I hope helpful you
private final OkHttpClient client = new OkHttpClient().newBuilder().connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS).addInterceptor(chain -> {
Request request = chain.request()
.newBuilder()
.addHeader("Accept", "application/json")
.addHeader("Content-Type", "application/json; charset=utf-8")
.addHeader("Authorization",sessionManagement.getSessionToken() != null ? "Bearer " + sessionManagement.getSessionToken(): "")
.build();
return chain.proceed(request);
})
.addInterceptor(logging)
.build();
Interceptor that you set works in sequence that you set
It means if you set authInterceptor before logging then first authInterceptor executed and then logging will start to print so here you just need to change sequence
From
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(authInterceptor)
.addInterceptor(logging)
.cookieJar(cookieJar)
.build();
To
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(logging)
.addInterceptor(authInterceptor)
.cookieJar(cookieJar)
.build();
It looks like maybe my token was missing, because the original sequence seems to work fine now that I moved the code outside of the if statement (for now):
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(authInterceptor)
.addInterceptor(logging)
.cookieJar(cookieJar)
.build();
And my AuthInterceptor now looks like this:
requestBuilder.addHeader("Accept", "application/json")
.addHeader("Content-Type", "application/json; charset=utf-8")
.addHeader("Authorization", "Bearer " + token);
However, I was wondering why I wasn't getting a header with the json response. Is this supposed to also be handled by the Interceptor?
For the time being, I went ahead and added headers to my php code before passing back a response. I am not sure if this is how it's actually supposed to be done.
header("Accept: application/json");
header('Content-Type: application/json; charset=utf-8');
header("Authorization: Bearer " . $response['auth_token']);
echo json_encode($response);
exit;
I make similar request with postman and rest-assured with the same credentials and receiving different status codes. The only header which accept server is application/json. Data and url are similar. I tried to add headers from postman, but it failed. ResstAssured.auth() isn't fit for me. Maybe someone have solution or faced this problem.
Code example:
public Response userLogin() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("password", "pass");
jsonObject.put("account_name", "name");
jsonObject.put("email", "mail");
jsonObject.put("mfa_otp", 123456);
String url = "url";
return given()
.contentType(ContentType.JSON)
.body(jsonObject.toString())
.when()
.post(url)
.then()
.statusCode(200)
.extract()
.response();
}
Request:
Request method: POST
Request URI: url
Proxy: <none>
Request params: <none>
Query params: <none>
Form params: <none>
Path params: <none>
Content-Type=application/json; charset=UTF-8
Cookies: <none>
Multiparts: <none>
Body:
{
"password": "pass",
"account_name": "name",
"email": "mail"
}
Response:
HTTP/1.1 400 Bad Request
Date: Tue, 13 Apr 2021 19:27:16 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: nginx
X-Content-Type-Options: nosniff
X-Frame-Options: deny
Cache-Control: no-cache, no-store, must-revalidate
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: ETag, Link, X-Request-Id
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Request-Id: 4e74caf3fa982d27cb827b5f7ebf6942
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
{
"status": "Bad Request",
"message": "Missing required parameter.",
"errors": [
{
"code": "required",
"field": "account_name"
}
]
}
Postman:
I figured out why It's happening every time, the Rest assured by default adding UTF-8 charset to content type.
Add this code to rest assured config method and you will be just fine, hope it will help to you.
private RestAssuredConfig decodeCharset = config().encoderConfig(encoderConfig().appendDefaultContentCharsetToContentTypeIfUndefined(false));
My goal is to add Access-Control-Allow-Origins in the header.
The Spring Security Reference's clearly said to
Set a POJO as #EnableWebSecurity's bean.
Override a configure(HttpSecurity http) method.
Create a CorsConfigurationSource's bean.
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) {
http
.cors(withDefaults())
.httpBasic(withDefaults());
}
#Bean
protected CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Collections.singletonList("http://localhost:3000"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
#RestController
public class AccountController {
#GetMapping("/ping")
public String getPing() {
return "PONG";
}
}
What I did:
Run a Spring Boot's application with the above configuration
Send a Fetch request to http://localhost:8080/ping from a React client.
The actual result:
The response does not include Access-Control-Allow-Origin header, I think it should be in the OPTIONS request.
The expected result:
A success response.
I am confused... I did a curl and the Access-Control-Allow-Origin is present. I think there is something wrong with the client side handling the HttpBasic.
curl -v -H "Access-Control-Request-Method: POST" -H "Origin: http://localhost:3000" -X OPTIONS http://localhost:8080/ping
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> OPTIONS /ping HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.55.1
> Accept: */*
> Access-Control-Request-Method: POST
> Origin: http://localhost:3000
>
< HTTP/1.1 200
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Access-Control-Allow-Origin: http://localhost:3000
< Access-Control-Allow-Methods: GET,POST
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Length: 0
< Date: Fri, 26 Feb 2021 13:37:15 GMT
<
* Connection #0 to host localhost left intact
A Spring MVC controller needs to redirect the control flow of an app to a different url endpoint within the same app. But the current code is returning a blank page along with response headers that include the intended destination url as the forward header. When the contents of the forward header is pasted into the web browser, the intended endpoint is successfully called. What specific changes need to be made to the code below in order for the POST controller to successfully redirect the control flow to the intended destination endpoint instead of returning a blank page?
Here is the code for the Controller method:
#RequestMapping(method = RequestMethod.POST)
#ResponseStatus(value = HttpStatus.OK)
public ResponseEntity<?> auth(FormData formData, HttpServletRequest req, HttpServletResponse resp) {
System.out.println("11111111111111 inside POST");
HttpHeaders responseHeaders = new HttpHeaders();
boolean passedTheTest = true;//ACTUAL LOGIC IS OMITTED HERE FOR SIMPLICITY
if (passedTheTest) {
//SOME OFF TOPIC LOGIC HERE IS OMITTED
CsrfToken csrf = (CsrfToken) req.getAttribute(CsrfToken.class.getName());
String updateCsrf = csrf.getToken();
responseHeaders.set("XSRF-TOKEN", updateCsrf);
if(resp.getHeaders("Cache-Control")!=null){responseHeaders.put("Cache-Control" , new ArrayList<String>(resp.getHeaders("Cache-Control")));}
if(resp.getHeader("Content-Language")!=null){responseHeaders.set("Content-Language" , resp.getHeader("Content-Language"));}
if(resp.getHeader("Content-Length")!=null){responseHeaders.set("Content-Length" , resp.getHeader("Content-Length"));}
if(resp.getHeader("Date")!=null){responseHeaders.set("Date" , resp.getHeader("Date"));}
if(resp.getHeader("Expires")!=null){responseHeaders.set("Expires" , resp.getHeader("Expires"));}
if(resp.getHeader("Pragma")!=null){responseHeaders.set("Pragma" , resp.getHeader("Pragma"));}
if(resp.getHeader("Server")!=null){responseHeaders.set("Server" , resp.getHeader("Server"));}
if(resp.getHeader("X-Application-Context")!=null){responseHeaders.set("X-Application-Context" , resp.getHeader("X-Application-Context"));}
if(resp.getHeader("X-Frame-Options")!=null){responseHeaders.set("X-Frame-Options" , resp.getHeader("X-Frame-Options"));}
if(resp.getHeader("X-XSS-Protection")!=null){responseHeaders.set("X-XSS-Protection" , resp.getHeader("X-XSS-Protection"));}
if(resp.getHeader("x-content-type-options")!=null){responseHeaders.set("x-content-type-options" , resp.getHeader("x-content-type-options"));}
if(req.getSession().getAttribute("forwardTo")!=null){
String redirectTo = getValidUriFromAnotherFunction();
try {
URI location = new URI(redirectTo);
responseHeaders.setLocation(location);
} catch (URISyntaxException e) {e.printStackTrace();}
ResponseEntity<Void> forwardResponseEntity = new ResponseEntity<Void>(responseHeaders, HttpStatus.CREATED);
return forwardResponseEntity;
}
};
return new ResponseEntity<String>("aDifferentViewTemplateName", responseHeaders, HttpStatus.CREATED);
}
The request headers in the browser's developer tools are:
Host: localhost:7777
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:7777/path/to/controller_method
Cookie: JSESSIONID=911B34457B69F7729091DD97A160AD79; JSESSIONID=95AA730306330CF15E3776C495807354; XSRF-TOKEN=04ae2a0c-3c58-4e85-88bd-3818bb10402a
Connection: keep-alive
The response headers for the same POST are:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate, no-cache, no-store, max-age=0, must-revalidate
Content-Length: 0
Date: Sun, 29 May 2016 21:48:24 GMT
Expires: 0, 0
Location: http://localhost:7777/path/to/forward_destination?long_querystring
Pragma: no-cache, no-cache
Server: Apache-Coyote/1.1
X-Application-Context: application:7777, application:7777
X-Content-Type-Options: nosniff, nosniff
X-Frame-Options: DENY, DENY
X-XSS-Protection: 1; mode=block, 1; mode=block
XSRF-TOKEN: 04ae2a0c-3c58-4e85-88bd-3818bb10402a
The Spring Boot debug log for the same POST includes three sections, which have been separated as follows for improved readability:
Section of debug log that shows the SYSO inside the controller:
11111111111111 inside POST
redirectTo is: http://localhost:7777/path/to/forward_destination?long_querystring
Section of debug log AFTER the controller (most important?):
2016-05-29 14:48:24.489 DEBUG 5533 --- [io-7777-exec-10] o.s.s.w.a.ExceptionTranslationFilter : Chain processed normally
2016-05-29 14:48:24.489 DEBUG 5533 --- [io-7777-exec-10] w.c.HttpSessionSecurityContextRepository : SecurityContext 'org.springframework.security.core.context.SecurityContextImpl#42259e42: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#42259e42: Principal: org.springframework.security.core.userdetails.User#40fecce: Username: SomeUser; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ONE,ROLE_TWO; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#fffe3f86: RemoteIpAddress: 127.0.0.1; SessionId: 02A95844E8A829868542290D471503F5; Granted Authorities: ROLE_ONE, ROLE_TWO, ROLE_THREE' stored to HttpSession: 'org.apache.catalina.session.StandardSessionFacade#64307ead
2016-05-29 14:48:24.489 DEBUG 5533 --- [io-7777-exec-10] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
Instead of returning the 201 Created status code you should return a 3XX status code to ask the user agent to load a different web page. Otherwise the Location header has no "special" meaning.
So for example you can write:
ResponseEntity<Void> forwardResponseEntity = new ResponseEntity<Void>(responseHeaders, HttpStatus.MOVED_PERMANENTLY);
I'm trying to implement basic HTTP authentication using Restlet 2.1, and I just can't get it to work .. ! I'm using a ChallengeAuthenticator to setup Basic HTTP authentication. I have just one URI \test, for which I'm trying to get authentication working.
I build my code, then run it as a Web Application and then browse to http://localhost:8888/test to see if I get a prompt for a username/password, but I don't get any. I just get a blank screen.
Also when I browse to http://localhost:8888/test, I get the following written in Eclipse's Console:
WARNING: A response with a 200 (Ok) status should have an entity. Make sure that resource "http://localhost:8888/test" returns one or sets the status to 204 (No content).
When when I browse to http://user:password#localhost:8888/test, the result is exactly the same.
The HTTP headers (from Chrome) are as follows:
Request:
GET /test HTTP/1.1
Host: localhost:8888
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,ms;q=0.6
Response (no mention of Basic authentication):
HTTP/1.1 200 OK
Date: Fri, 13 Jun 2014 11:21:05 GMT
Accept-Ranges: bytes
Server: Development/1.0
Content-Length: 0
Cache-Control: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Here is the Java code:
package com.poc.hw7;
import org.restlet.*;
import org.restlet.data.ChallengeScheme;
import org.restlet.data.Cookie;
import org.restlet.data.MediaType;
import org.restlet.routing.Router;
import org.restlet.security.*;
import org.restlet.util.Series;
public class AuthTestApp extends Application {
private ChallengeAuthenticator authenticator;
private ChallengeAuthenticator createAuthenticator() {
Context context = getContext();
boolean optional = false;
ChallengeScheme challengeScheme = ChallengeScheme.HTTP_BASIC;
String realm = "Example site";
MapVerifier verifier = new MapVerifier();
verifier.getLocalSecrets().put("user", "password".toCharArray());
ChallengeAuthenticator auth = new ChallengeAuthenticator(context, optional, challengeScheme, realm, verifier) {
#Override
protected boolean authenticate(Request request, Response response) {
if (request.getChallengeResponse() == null) {
return false;
} else {
return super.authenticate(request, response);
}
}
};
return auth;
}
#Override
public Restlet createInboundRoot() {
this.authenticator = createAuthenticator();
Restlet hw_restlet = new Restlet(getContext())
{
public void handle(Request request, Response response)
{
String message = "Hello World!";
response.setEntity(message,MediaType.TEXT_PLAIN);
}
};
Router router = new Router();
router.attach("/test", hw_restlet);
authenticator.setNext(router);
return authenticator;
}
public boolean authenticate(Request request, Response response) {
if (!request.getClientInfo().isAuthenticated()) {
authenticator.challenge(response, false);
return false;
}
return true;
}
}
Here is the web.xml file:
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>Restlet URI Rewrite</display-name>
<servlet>
<servlet-name>RestletServlet</servlet-name>
<servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class>
<init-param>
<param-name>org.restlet.application</param-name>
<param-value>com.poc.hw7.AuthTestApp</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>RestletServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Can someone please tell me how to get basic HTTP authentication working ?
Your response was a 200 code, which means your server never asked for one. You would need to send a 401 response. For most web browsers, this will automatically pop up the basic-auth box for a username and password.
As for why this is happening... it's hard to say. restlet looks very... bad. There are easier frameworks to work with, where you can just annotate a function to listen to a certain URI and/or request method.