- Angular v. v4.0.2
- Spring Boot v. 1.5.2.RELEASE
- Keycloak v.2.4.0.Final (will upgrade later)
I read this mail converstion about the same problem: http://keycloak-user.88327.x6.nabble.com/keycloak-user-NOT-ATTEMPTED-bearer-only-error-while-trying-to-access-server-from-client-td927.html and this http://slackspace.de/articles/authentication-with-spring-boot-angularjs-and-keycloak/
I use the following http service for making authorized requests:
@Injectable()
export class AuthHttpService extends Http {
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private authService: AuthService) {
super(backend, defaultOptions);
}
private setToken(options: RequestOptionsArgs) {
if (options == null || AuthService.auth == null || AuthService.auth.authz == null || AuthService.auth.authz.token == null) {
console.log("Need a token, but no token is available, not setting bearer token.");
return;
}
console.log(AuthService.auth.authz.token);
options.headers.set('Authorization', 'Bearer ' + AuthService.auth.authz.token);
}
private configureRequest(f:Function, url:string | Request, options:RequestOptionsArgs, body?: any):Observable<Response> {
let tokenPromise:Promise<string> = this.authService.getToken();
let tokenObservable:Observable<string> = Observable.fromPromise(tokenPromise);
let tokenUpdateObservable:Observable<any> = Observable.create((observer) => {
if (options == null) {
let headers = new Headers();
options = new RequestOptions({ headers: headers });
}
this.setToken(options);
observer.next();
observer.complete();
});
let requestObservable:Observable<Response> = Observable.create((observer) => {
let result;
if (body) {
result = f.apply(this, [url, body, options]);
} else {
result = f.apply(this, [url, options]);
}
result.subscribe((response) => {
observer.next(response);
observer.complete();
}, (err) => observer.error(err));
});
return <Observable<Response>>Observable
.merge(tokenObservable, tokenUpdateObservable, requestObservable, 1)
.filter((response) => response instanceof Response);
}
...
Application.properties
The token is correctly logged.
server.port = 8081
keycloak.realm = apprealm
keycloak.auth-server-url = http://localhost:8080/auth
keycloak.ssl-required = external
keycloak.resource = appbackend
keycloak.bearer-only = true
keycloak.credentials.secret = ...
keycloak.securityConstraints[0].securityCollections[0].name = secure
keycloak.securityConstraints[0].securityCollections[0].authRoles[0]=frontenduser
keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /r/s/*
logging.level.org.keycloak=DEBUG
The user which I use in the frontend has that role.
Error in backend
2017-04-22 15:40:00.517 DEBUG 14088 --- [nio-8081-exec-1] o.k.adapters.PreAuthActionsHandler : adminRequest http://localhost:8081/r/s/e/p/m
2017-04-22 15:40:00.540 DEBUG 14088 --- [nio-8081-exec-1] o.k.a.a.ClientCredentialsProviderUtils : Using provider 'secret' for authentication of client 'appbackend'
2017-04-22 15:40:00.543 DEBUG 14088 --- [nio-8081-exec-1] o.k.a.a.ClientCredentialsProviderUtils : Loaded clientCredentialsProvider secret
2017-04-22 15:40:00.545 DEBUG 14088 --- [nio-8081-exec-1] o.k.a.a.ClientCredentialsProviderUtils : Loaded clientCredentialsProvider jwt
2017-04-22 15:40:00.552 DEBUG 14088 --- [nio-8081-exec-1] o.k.a.a.ClientCredentialsProviderUtils : Loaded clientCredentialsProvider secret
2017-04-22 15:40:00.553 DEBUG 14088 --- [nio-8081-exec-1] o.k.a.a.ClientCredentialsProviderUtils : Loaded clientCredentialsProvider jwt
2017-04-22 15:40:00.625 DEBUG 14088 --- [nio-8081-exec-1] o.keycloak.adapters.KeycloakDeployment : resolveUrls
2017-04-22 15:40:00.631 DEBUG 14088 --- [nio-8081-exec-1] o.k.adapters.KeycloakDeploymentBuilder : Use authServerUrl: http://localhost:8080/auth, tokenUrl: http://localhost:8080/auth/realms/apprealm/protocol/openid-connect/token, relativeUrls: NEVER
2017-04-22 15:40:00.662 DEBUG 14088 --- [nio-8081-exec-1] o.k.adapters.RequestAuthenticator : NOT_ATTEMPTED: bearer only
2017-04-22 15:40:00.681 INFO 14088 --- [nio-8081-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2017-04-22 15:40:00.681 INFO 14088 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2017-04-22 15:40:00.723 INFO 14088 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 42 ms
2017-04-22 15:40:08.560 DEBUG 14088 --- [nio-8081-exec-2] o.k.adapters.PreAuthActionsHandler : adminRequest http://localhost:8081/r/s/e/p/m
2017-04-22 15:40:08.560 DEBUG 14088 --- [nio-8081-exec-2] o.k.adapters.RequestAuthenticator : NOT_ATTEMPTED: bearer only
Edit http
HTTP/1.1 401
Cache-Control: private
Expires: Thu, 01 Jan 1970 01:00:00 CET
WWW-Authenticate: Bearer realm="apprealm"
Access-Control-Allow-Origin: http://localhost:4200
Vary: Origin
Access-Control-Allow-Methods: GET,POST,PUT,DELETE
Access-Control-Allow-Headers: authorization, content-type
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1800
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Content-Length: 0
Date: Sun, 23 Apr 2017 17:04:07 GMT
Edit 2: http raw request
OPTIONS http://localhost:8081/r/p/main HTTP/1.1
Host: localhost:8081
Connection: keep-alive
Access-Control-Request-Method: PUT
Origin: http://localhost:4200
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Access-Control-Request-Headers: authorization,content-type
Accept: */*
Referer: http://localhost:4200/b
Accept-Encoding: gzip, deflate, sdch
Accept-Language: nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4
What could be the problem?