jersey and ios basic authentication

Main goal is to authenticate an ios client against a REST service build with jersey and http basic authentication (rfc2617).

As I wanted authentication to be done by jersey and not tomcat, I needed to add WWW-Authentication header field. This is handled at unauthorized custom exception (found at thisĀ post, thanks!!!).

Client

[sourcecode language=”objc”]

– (IBAction)loginPush:(id)sender {
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:@"http:url.kom"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];

NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
}

– (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
}

– (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}

– (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
return YES;
}

– (void)connectionDidFinishLoading:(NSURLConnection *)connection {

}

– (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSURLCredential *newCredential = [NSURLCredential credentialWithUser:@"user"
password:@"password"
persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
}

[/sourcecode]

Server

Jersey resource

[sourcecode language=”java”]
@Path("/hello")
public class HelloResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String sayHello() {
return "Hello Jersey";
}
}
[/sourcecode]

Jersey filter

[sourcecode language=”java”]
public class AuthFilter implements ContainerRequestFilter {

private final static WebApplicationException unauthorized =
new WebApplicationException(
Response.status(Status.UNAUTHORIZED)
.header(HttpHeaders.WWW_AUTHENTICATE, "Basic realm="realm"")
.entity("Page requires login.").build());
@Override
public ContainerRequest filter(ContainerRequest containerRequest) throws WebApplicationException {

String auth = containerRequest.getHeaderValue("authorization");

if(auth == null){
throw unauthorized;
}

String[] lap = BasicAuth.decode(auth);

if(lap == null || lap.length != 2){
throw unauthorized;
}

if(!lap[0].equals("user") || !lap[1].equals("password")){
throw unauthorized;
}

return containerRequest;
}
}
[/sourcecode]

web.xml
[sourcecode language=”xml”]
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>Hello jersey REST Service</servlet-name>
<servlet-class>
com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>sample.hello.resources</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
<param-value>sample.hello.resources.AuthFilter</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Hello jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
[/sourcecode]