SpringBoot 2.7.8 Infinity loop authenticate on BadCredentialsException while use ActiveDirectoryLdapAuthenticationProvider - active-directory

Need Help!
Loop with stackowerflow only while unsuccessful authorization via AD
1 authenticate: 201, ProviderManager (org.springframework.security.authentication) [5]
#Bean
public ActiveDirectoryLdapAuthenticationProvider getLdapAuthenticationProvider() {
BindAuthenticator bindAuthenticator = new BindAuthenticator(contextSource());
bindAuthenticator.setUserDnPatterns(new String[]{userDNPattern});
ActiveDirectoryLdapAuthenticationProvider authenticationProvider =
new ActiveDirectoryLdapAuthenticationProvider(null, ldapUrl, ldapPartitionSuffix);
authenticationProvider.setConvertSubErrorCodesToExceptions(true);
authenticationProvider.setUseAuthenticationRequestCredentials(true);
if (userDNPattern != null && userDNPattern.trim().length() > 0) {
authenticationProvider.setSearchFilter(userDNPattern);
}
return authenticationProvider;
}
#Bean
public AuthenticationManager authManager(HttpSecurity http) throws Exception {
AuthenticationManagerBuilder authBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
authBuilder.authenticationProvider(getLdapAuthenticationProvider());
return authBuilder.build();
}

Related

Getting Unauthorized error: Full authentication is required to access this resource

I'm implementing JWT and Spring Security for authentication in my application.
I have 3 roles: Admin, Moderator and User.
For example, after logging with user role, I got the home page, but once I go to hit the user space by clicking on a button, I got:
2020-09-04 09:01:22.819 ERROR 10148 --- [nio-8080-exec-5]
c.b.s.security.jwt.AuthEntryPointJwt : Unauthorized error: Full
authentication is required to access this resource
the file webSecurityConfig.java is:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(
// securedEnabled = true,
// jsr250Enabled = true,
prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsServiceImpl userDetailsService;
#Autowired
private AuthEntryPointJwt unauthorizedHandler;
#Bean
public AuthTokenFilter authenticationJwtTokenFilter() {
return new AuthTokenFilter();
}
#Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests().antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/test/**").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
The class AuthEntryPointJwt is:
#Component
public class AuthEntryPointJwt implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(AuthEntryPointJwt.class);
#Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
logger.error("Unauthorized error: {}", authException.getMessage());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error: Unauthorized");
}
}
The class AuthTokenFilter is:
public class AuthTokenFilter extends OncePerRequestFilter {
#Autowired
private JwtUtils jwtUtils;
#Autowired
private UserDetailsServiceImpl userDetailsService;
private static final Logger logger = LoggerFactory.getLogger(AuthTokenFilter.class);
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
String jwt = parseJwt(request);
if (jwt != null && jwtUtils.validateJwtToken(jwt)) {
String username = jwtUtils.getUserNameFromJwtToken(jwt);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception e) {
logger.error("Cannot set user authentication: {}", e);
}
filterChain.doFilter(request, response);
}
private String parseJwt(HttpServletRequest request) {
String headerAuth = request.getHeader("Authorization");
if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
return headerAuth.substring(7, headerAuth.length());
}
return null;
}
}
The class JwtUtils is:
#Component
public class JwtUtils {
private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
#Value("${bezkoder.app.jwtSecret}")
private String jwtSecret;
#Value("${bezkoder.app.jwtExpirationMs}")
private int jwtExpirationMs;
public String generateJwtToken(Authentication authentication) {
UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal();
return Jwts.builder()
.setSubject((userPrincipal.getUsername()))
.setIssuedAt(new Date())
.setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
.signWith(SignatureAlgorithm.HS512, jwtSecret)
.compact();
}
public String getUserNameFromJwtToken(String token) {
return Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody().getSubject();
}
public boolean validateJwtToken(String authToken) {
try {
Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
return true;
} catch (SignatureException e) {
logger.error("Invalid JWT signature: {}", e.getMessage());
} catch (MalformedJwtException e) {
logger.error("Invalid JWT token: {}", e.getMessage());
} catch (ExpiredJwtException e) {
logger.error("JWT token is expired: {}", e.getMessage());
} catch (UnsupportedJwtException e) {
logger.error("JWT token is unsupported: {}", e.getMessage());
} catch (IllegalArgumentException e) {
logger.error("JWT claims string is empty: {}", e.getMessage());
}
return false;
}
}
The class AuthController is:
#CrossOrigin(origins = "*", maxAge = 3600)
#RestController
#RequestMapping("/api/auth")
public class AuthController {
#Autowired
AuthenticationManager authenticationManager;
#Autowired
UserRepository userRepository;
#Autowired
RoleRepository roleRepository;
#Autowired
PasswordEncoder encoder;
#Autowired
JwtUtils jwtUtils;
#PostMapping("/signin")
public ResponseEntity<?> authenticateUser(#Valid #RequestBody LoginRequest loginRequest) {
System.out.println("---------------- auth 1 ");
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = jwtUtils.generateJwtToken(authentication);
UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
List<String> roles = userDetails.getAuthorities().stream()
.map(item -> item.getAuthority())
.collect(Collectors.toList());
return ResponseEntity.ok(new JwtResponse(jwt,
userDetails.getId(),
userDetails.getUsername(),
userDetails.getEmail(),
roles));
}
#GetMapping("/user")
#PreAuthorize("hasRole('USER') or hasRole('MODERATOR') or hasRole('ADMIN')")
public String userAccess()
{
System.out.println("---------------- test User ");
return "User Content.";
}
}
The file application.properties, I put:
spring.datasource.url=...
spring.datasource.username=...
spring.datasource.password=...
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation= true
spring.jpa.properties.hibernate.dialect=...
spring.jpa.hibernate.ddl-auto=update
bezkoder.app.jwtSecret= bezKoderSecretKey
bezkoder.app.jwtExpirationMs= 86400000
In Browser console, I got that exception.
Could you please help me solving that issue ?. Big thanks.
You have to update WebSecurityConfig according to your Controller mapping.
.antMatchers("/**").permitAll()
.anyRequest().authenticated();
You probably are testing in wrong in postman or amneasia or whatever API testing tool you are using. If you are using postman :
1.Select the Header tab
2.Click the button that says "hide auto-generated headers"
3.Type "Authorization" (without quotes) under the "Key" column.
4.Type "Bearer" under the "Value" column then paste the token. Ensure there is a space between "Bearer" and the "Token".
5.Send the request
You should comment #PreAuthorize("hasRole('USER') or hasRole('MODERATOR') or hasRole('ADMIN')").
Tell about the result ?.

DaoAuthenticationProvider not getting invoked

I am trying to authenticate a request from using spring security, I have followed few blogs and videos but i am not able to fix the issues.
Security configuration is loaded but my requests are not getting authenticated. I get 403 error
Bean class in WebSecurityConfigureAdapter
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userService);
System.out.println(userDetailsService());
return authProvider;
}
over riding configure method
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers("/products","/orders").hasAnyRole("admin");//.authenticated();
}
user details services overridding loadUserByUsername
#Override
public UserDetails loadUserByUsername(String loginName) {
String authenticated = "false";
UserDetails userDetails = null;
List<Users> usersList = usersRepository.findByLoginName(loginName);
if(usersList.size()==0) {
return null;
}else {
for (Users users : usersList) {
List<Roles> rolesList = users.getRoles();
for (Roles roles : rolesList) {
if(roles.getUserRole().equalsIgnoreCase("admin")) {
authenticated = "admin";
GrantedAuthority authority = new SimpleGrantedAuthority(authenticated);
User user = new User(users.getLoginName(),users.getPassword(),Arrays.asList(authority));
userDetails = (UserDetails)user;
}
}
}
return userDetails;
}
using postman setting up the credentials as basicAuth, its throwing 403 error
the issue was...
we need to either set the value for different getters in userdetails class or explicitly set to true
i have below getters explicitly set it to true, it worked for me
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}

Solr 7 with Spring data and basic authentication not working

#SpringBootApplication
public class SpringDataSolarApplication {
public static void main(String[] args) {
SpringApplication.run(SpringDataSolarApplication.class, args);
}
#Bean
SolrTemplate solrTemplate() {
return new SolrTemplate(solrClientFactory());
}
#Bean
SolrClientFactory solrClientFactory() {
Credentials credentials = new UsernamePasswordCredentials("solr", "SolrRocks");
return new HttpSolrClientFactory(solrClient(), credentials , "BASIC");
}
#Bean
SolrClient solrClient() {
return new HttpSolrClient.Builder("http://localhost:8983/solr").build();
}
}
public interface EmployeeRepository extends SolrCrudRepository{
Employee findByName(String name);
}
#RestController
public class EmployeeController {
#Autowired
private EmployeeRepository repository;
#PostConstruct
public void addEmployees() {
List<Employee> employees = new ArrayList<>();
employees.add(new Employee("373", "Basant", new String[] { "Bangalore", "BTM" }));
employees.add(new Employee("908", "Santosh", new String[] { "Hyderbad", "XYZ" }));
employees.add(new Employee("321", "Sagar", new String[] { "Pune", "PQR" }));
repository.saveAll(employees);
}
#GetMapping("/getALL")
public Iterable<Employee> getEmployees() {
return repository.findAll();
}
#GetMapping("/getEmployee/{name}")
public Employee getEmployeeByName(#PathVariable String name) {
return repository.findByName(name);
}
}
the getALL operation is working fine but the save operation failed with this error. Please help
Caused by: org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity.
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:225) ~[httpclient-4.5.7.jar:4.5.7]
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185) ~[httpclient-4.5.7.jar:4.5.7]
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) ~[httpclient-4.5.7.jar:4.5.7]
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) ~[httpclient-4.5.7.jar:4.5.7]
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) ~[httpclient-4.5.7.jar:4.5.7]
... 63 common frames omitted
Came across same issue and solved with extending HttpSolrClient and applying same backend approach with recommended way mentioned on Solr docs but getting credentials from constructor not setting on each request.
class CustomSolrClient extends HttpSolrClient {
#Nullable
private final String username;
#Nullable
private final String password;
CustomSolrClient(Builder builder, String username, String password) {
super(builder);
this.username = username;
this.password = password;
}
#Override
public NamedList<Object> request(SolrRequest request, ResponseParser processor, String collection) throws SolrServerException, IOException {
HttpRequestBase method = createMethod(request, collection);
if (username != null && password != null) {
String userPass = username + ":" + password;
String encoded = Base64.byteArrayToBase64(userPass.getBytes(UTF_8));
method.setHeader(new BasicHeader("Authorization", "Basic " + encoded));
}
return executeMethod(method, processor, request instanceof V2Request || request.getPath().contains("/____v2"));
}
}
And create bean using that:
#Bean
public SolrClient solrClient() {
return new CustomSolrClient(new HttpSolrClient.Builder(properties.getHost()), properties.getUsername(), properties.getPassword());
}
This may seem as an ugly approach but if you check HttpSolrClientFactory sources it's even more uglier which actually accesses private field of HttpClient belongs to Solr client.

Spring-boot angularjs satelizer cors filter

Have a problem with CORS filter, i think.
Because when i send request with Authorization header by Intellij Idea REST Tools, my filter catch a Authorization header.
But when i try to send request from client side from another server, filter does not see my header(return null).
I`m using spring boot, angularjs, salelizer and JWT for build token.
Params for building token on server side.
private static final JWSHeader JWT_HEADER = new JWSHeader(JWSAlgorithm.HS256);
private static final String TOKEN_SECRET = "Bearer";
public static final String AUTH_HEADER_KEY = "Authorization";
My Auth filter
public class AuthFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String authHeader = httpRequest.getHeader(AuthUtils.AUTH_HEADER_KEY);
if (StringUtils.isBlank(authHeader) || authHeader.split(" ").length != 2) {
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, AUTH_ERROR_MSG);
} else {
JWTClaimsSet claimSet = null;
try {
claimSet = (JWTClaimsSet) AuthUtils.decodeToken(authHeader);
} catch (ParseException e) {
httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, JWT_ERROR_MSG);
return;
} catch (JOSEException e) {
httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, JWT_INVALID_MSG);
return;
}
// ensure that the token is not expired
if (new DateTime(claimSet.getExpirationTime()).isBefore(DateTime.now())) {
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, EXPIRE_ERROR_MSG);
} else {
chain.doFilter(request, response);
}
}
}
#Override
public void destroy() { /* unused */ }
#Override
public void init(FilterConfig filterConfig) throws ServletException { /* unused */ }
}
My CORS filter in Web Mvc config file
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.addExposedHeader("Authorization");
config.addExposedHeader("Content-Type");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
My security configure
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,"**").permitAll().and().authorizeRequests()
.antMatchers( "/index","/api/**", "/auth/**", "/js/**", "/css/**", "/html/**")
.permitAll().anyRequest().authenticated();
My cliend side configs
function configHttp($httpProvider, $authProvider){
console.log("sdfd");
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
$httpProvider.defaults.headers.common["Accept"] = "application/json";
$httpProvider.defaults.headers.common["Content-Type"] = "application/json";
var token = sessionStorage.getItem("satellizer_token");
if (token && $authProvider.httpInterceptor) {
token = $authProvider.authHeader === 'Authorization' ? 'Bearer ' + token : token;
$httpProvider.defaults.headers.common[$authProvider.authHeader] = token;
}
}
function configAuth($authProvider) {
$authProvider.httpInterceptor = function() { return true; };
$authProvider.baseUrl = 'http://localhost:8080';
$authProvider.loginUrl = '/auth/login';
$authProvider.signupUrl = '/auth/registration';
$authProvider.tokenName = 'token';
$authProvider.storageType = 'sessionStorage';
$authProvider.authToken = 'Bearer';
$authProvider.authHeader = 'Authorization';
}
There are a few options described here.
One option would be to annotate your controller method or class with #CrossOrigin.
If you want global config, you could add a new bean. I took this from the Spring doc listed above and modified it so that the mapping is /*. You can modify that path to be suitable for your application. According to the javadoc all origins will be allowed by default.
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/*");
}
};
}

Using OkHttp client via OKClient on Google App Engine throws a "java.lang.NoClassDefFoundError: java.net.ProxySelector" is a restricted class error

I am trying to use OKHTTP (version 2.4.0) along retrofit (1.9.0) on google app engine (1.9.22).
Here is the how i use it:
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setConnectTimeout(COMPOSER_MODULE_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
okHttpClient.setReadTimeout(COMPOSER_MODULE_SOCKET_TIMEOUT, TimeUnit.SECONDS);
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setConverter(new JacksonConverter())
.setEndpoint(ENDPOINT_PATH)
.setClient(new OkClient(okHttpClient))
.build();
This throws the following error:
java.lang.NoClassDefFoundError: java.net.ProxySelector is a restricted class. Please see the Google App Engine developer's guide for more details.
at com.google.apphosting.runtime.security.shared.stub.java.net.ProxySelector.<clinit>(ProxySelector.java)
at com.squareup.okhttp.OkHttpClient.copyWithDefaults(OkHttpClient.java:614)
at com.squareup.okhttp.Call.<init>(Call.java:50)
at com.squareup.okhttp.OkHttpClient.newCall(OkHttpClient.java:595)
at retrofit.client.OkClient.execute(OkClient.java:53)
I gather from the error that "java.net.ProxySelector" is not white-listed for use on google appengine.
Question 1)
Is it possible to use OKHTTP (version 2.4.0) along retrofit (1.9.0) on google app engine (1.9.22)? i.e, is there a work around for this error
if not,
Question 2)
Are there any other way to:
(a) use async HTTP calls with google appengine (with URLFetchService, for instance) ?
(b) set connection and socket timeouts for the client used from (a) ?
The links i have come across via search:
(1) Retrofit timeout configuration for clients
(2) Google App Engine URL Fetch Java API
You can use HttpUrlConnection with Retrofit2 to use it in Google APP Engine
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.servlet.http.HttpServletResponse;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.BufferedSink;
import okio.BufferedSource;
import okio.Okio;
public class RetrofitCall implements Call {
Request request;
RetrofitCall(Request request) {
this.request = request;
}
#Override
public Request request() {
return request;
}
#Override
public Response execute() throws IOException {
URL url = request.url().url();
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setUseCaches(false);
connection.setDoOutput(true);
connection.setRequestMethod(request.method());
Headers headers = request.headers();
if (headers != null) {
for (int i = 0; i < headers.size(); i++) {
String name = headers.name(i);
connection.setRequestProperty(name, headers.get(name));
}
}
if (request.body() != null) {
BufferedSink outbuf;
outbuf = Okio.buffer(Okio.sink(connection.getOutputStream()));
request.body().writeTo(outbuf);
outbuf.close();
}
connection.connect();
final BufferedSource source = Okio.buffer(Okio.source(connection.getInputStream()));
if (connection.getResponseCode() != HttpServletResponse.SC_OK) {
throw new IOException("Fail to call " + " :: " + source.readUtf8());
}
Response response = new Response.Builder()
.code(connection.getResponseCode())
.message(connection.getResponseMessage())
.request(request)
.protocol(Protocol.HTTP_1_1)
.body(new ResponseBody() {
#Override
public MediaType contentType() {
return MediaType.parse(connection.getContentType());
}
#Override
public long contentLength() {
return connection.getContentLengthLong();
}
#Override
public BufferedSource source() {
return source;
}
})
.build();
return response;
}
#Override
public void enqueue(Callback responseCallback) {
}
#Override
public void cancel() {
}
#Override
public boolean isExecuted() {
return false;
}
#Override
public boolean isCanceled() {
return false;
}
public static class Factory implements Call.Factory {
#Override
public Call newCall(Request request) {
return new RetrofitCall(request);
}
}
}
You can use the following code snippet to run Retorifit2 with GAE limitations. It contains a lot of debugging stuffs free to remove in production and does not implement real async call.
okhttp3.Call.Factory gaeCallFactory = new okhttp3.Call.Factory() {
#Override
public okhttp3.Call newCall(final Request request) {
final URL url = request.url().url();
final String method = url.toString();
return new okhttp3.Call() {
#Override
public Request request() {
return request;
}
#Override
public Response execute() throws IOException {
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setUseCaches(false);
if (request.body() != null) {
//TODO ajust for different needs
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
BufferedSink outbuf;
ByteArrayOutputStream out = new ByteArrayOutputStream();
outbuf = Okio.buffer(Okio.sink(out));
request.body().writeTo(outbuf);
outbuf.close();
logger.info("Calling " + method + "\n" + new String(out.toByteArray()));
outbuf = Okio.buffer(Okio.sink(connection.getOutputStream()));
request.body().writeTo(outbuf);
outbuf.close();
} else {
logger.info("Calling " + method);
}
final BufferedSource source = Okio.buffer(Okio.source(connection.getInputStream()));
if (connection.getResponseCode() != HttpServletResponse.SC_OK) {
throw new IOException("Fail to call " + method + " :: " + source.readUtf8());
}
Response response = new Response.Builder()
.code(connection.getResponseCode())
.message(connection.getResponseMessage())
.request(request)
.protocol(Protocol.HTTP_1_1)
.body(new ResponseBody() {
#Override
public MediaType contentType() {
return MediaType.parse(connection.getContentType());
}
#Override
public long contentLength() {
return connection.getContentLengthLong();
}
#Override
public BufferedSource source() {
return source;
}
})
.build();
logger.info("Call response code: " + response.code() + " message: " + response.message());
return response;
}
#Override
public void enqueue(Callback responseCallback) {
try {
responseCallback.onResponse(this, execute());
} catch (IOException e) {
responseCallback.onFailure(this, e);
}
}
#Override
public void cancel() {
}
#Override
public boolean isExecuted() {
return false;
}
#Override
public boolean isCanceled() {
return false;
}
};
}
};
Retrofit retrofit = new Retrofit.Builder()
.callFactory(gaeCallFactory)
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(ENDPOINT_URI)
.build();
You need to use the Appengine URLFetchClient instead of the OkHttpClient. Like this:
import retrofit.appengine.UrlFetchClient;
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setConverter(new JacksonConverter())
.setEndpoint(ENDPOINT_PATH)
.setClient(new UrlFetchClient())
.build();
Please note this only works with Retrofit1, this will not work with Retrofit2 because it's coupled directly to OkHttp as explained by Jake Wharton here

Resources