--
You received this message because you are subscribed to the Google Groups "HAPI FHIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hapi-fhir+unsubscribe@googlegroups.com.
To post to this group, send email to hapi...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/hapi-fhir/62732501-bf4f-48ae-b235-92dc99139a02%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
2016-12-05 14:09:49.728 [qtp1040385133-17] WARN ca.uhn.fhir.to.BaseController [BaseController.java:396] Failed to load conformance statementca.uhn.fhir.rest.server.exceptions.AuthenticationException: HTTP 401 Unauthorized: Missing Authorization header value at sun.reflect.GeneratedConstructorAccessor112.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Unknown Source) at ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException.newInstance(BaseServerResponseException.java:307) at ca.uhn.fhir.rest.client.BaseClient.invokeClient(BaseClient.java:290) at ca.uhn.fhir.rest.client.BaseClient.invokeClient(BaseClient.java:183) at ca.uhn.fhir.rest.client.GenericClient.conformance(GenericClient.java:105) at ca.uhn.fhir.to.BaseController.loadAndAddConfDstu2(BaseController.java:394) at ca.uhn.fhir.to.BaseController.loadAndAddConf(BaseController.java:321) at ca.uhn.fhir.to.BaseController.addCommonParams(BaseController.java:97) at ca.uhn.fhir.to.Controller.actionHome(Controller.java:230) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) at javax.servlet.http.HttpServlet.service(HttpServlet.java:687) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:845) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1689) at org.ebaysf.web.cors.CORSFilter.handleNonCORS(CORSFilter.java:437) at org.ebaysf.web.cors.CORSFilter.doFilter(CORSFilter.java:172) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1668) at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:225) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213) at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:119) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134) at org.eclipse.jetty.server.Server.handle(Server.java:524) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253) at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273) at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95) at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93) at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303) at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148) at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671) at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589) at java.lang.Thread.run(Unknown Source)
--
You received this message because you are subscribed to the Google Groups "HAPI FHIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hapi-fhir+unsubscribe@googlegroups.com.
To post to this group, send email to hapi...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/hapi-fhir/ae5e1184-c159-4681-bff8-ee720ae7ec43%40googlegroups.com.
Thanks RonaldIn this sample I have to set the header. Can you suggest.me the proper way of setting the header.Please check out the snaps I have attached.
--
You received this message because you are subscribed to the Google Groups "HAPI FHIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hapi-fhir+unsubscribe@googlegroups.com.
To post to this group, send email to hapi...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/hapi-fhir/513ce250-2ea6-42b1-ab49-2cd602b56b67%40googlegroups.com.
--
You received this message because you are subscribed to a topic in the Google Groups "HAPI FHIR" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/hapi-fhir/0ewrCc4v_Sk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to hapi-fhir+unsubscribe@googlegroups.com.
To post to this group, send email to hapi...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/hapi-fhir/a9f09439-12fb-4f23-b8c5-918802174540%40googlegroups.com.
package ca.uhn.fhir.jpa.demo; import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.server.exceptions.AuthenticationException; import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor; import ca.uhn.fhir.rest.server.interceptor.auth.IAuthRule; import ca.uhn.fhir.rest.server.interceptor.auth.RuleBuilder; import org.jose4j.jwk.HttpsJwks; import org.jose4j.jwt.JwtClaims; import org.jose4j.jwt.consumer.InvalidJwtException; import org.jose4j.jwt.consumer.JwtConsumer; import org.jose4j.jwt.consumer.JwtConsumerBuilder; import org.jose4j.keys.resolvers.HttpsJwksVerificationKeyResolver; import org.json.JSONObject; import java.util.Base64; import java.util.List; /** * Created by LarsKristian on 12.09.2016. */ public class OAuthAuthorizationInterceptor extends AuthorizationInterceptor { private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(OAuthAuthorizationInterceptor.class); @Override public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) { // Check if request has authorization header and Bearer token if (theRequestDetails.getHeader("Authorization") == null) { // Throw an HTTP 401 throw new AuthenticationException("Missing Authorization header value"); } else if (!theRequestDetails.getHeader("Authorization").toUpperCase().startsWith("BEARER ")) { logger.error("Bearer not found (do not log in production!) = " + theRequestDetails.getHeader("Authorization")); throw new AuthenticationException("Missing Bearer token in Authorization header (must start with 'Bearer')"); } String authHeader = theRequestDetails.getHeader("Authorization"); String encodedAccessToken = authHeader.split(" ")[1]; logger.info("Authorization header (do not log in production!) = " + authHeader); logger.info("encodedAccessToken (do not log in production!) = "+encodedAccessToken); JSONObject decodedAccessTokenBody = null; boolean isJWTValid = false; boolean userIsAdmin = false; IdDt userIdPatientId = null; try { decodedAccessTokenBody = getDecodedJSONObject(encodedAccessToken.split("\\.")[1]); isJWTValid = checkNHNAuthorization(encodedAccessToken, decodedAccessTokenBody); } catch (Exception e) { throw new AuthenticationException("Error parsing Bearer token (is it a valid JWT?)"); } if (isJWTValid) { // TODO: Only give access to ONE patient! userIsAdmin = true; // This user has access only to Patient/1 resources //userIdPatientId = new IdDt("Patient", 1L); } else { // Throw an HTTP 401 throw new AuthenticationException("Bearer token not accepted"); } // If the user is a specific patient, we create the following rule chain: // Allow the user to read anything in their own patient compartment // Allow the user to write anything in their own patient compartment // If a client request doesn't pass either of the above, deny it if (userIdPatientId != null) { return new RuleBuilder() .allow().read().allResources().inCompartment("Patient", userIdPatientId).andThen() .allow().write().allResources().inCompartment("Patient", userIdPatientId).andThen() .denyAll() .build(); } // If the user is an admin, allow everything if (userIsAdmin) { return new RuleBuilder() .allowAll() .build(); } // By default, deny everything. This should never get hit, but it's // good to be defensive return new RuleBuilder() .denyAll() .build(); } private boolean checkNHNAuthorization(String encodedAccessToken, JSONObject decodedAccessTokenBody) { // Check Access Token HttpsJwks httpsJkws = new HttpsJwks("https://adfs.fia.nhn.no/adfs/discovery/keys"); HttpsJwksVerificationKeyResolver httpsJwksKeyResolver = new HttpsJwksVerificationKeyResolver(httpsJkws); JwtConsumer jwtConsumer = new JwtConsumerBuilder() .setRequireExpirationTime() // the JWT must have an expiration time .setAllowedClockSkewInSeconds(180) // allow some leeway in validating time based claims to account for clock skew //.setRequireSubject() // the JWT must have a subject claim .setExpectedIssuer("http://adfs.fia.nhn.no/adfs/services/trust") // whom the JWT needs to have been issued by .setExpectedAudience("http://apps.ehelselab.com/velferd/api/") // to whom the JWT is intended for .setVerificationKeyResolver(httpsJwksKeyResolver) .build(); try { // Validate the JWT and process it to the Claims JwtClaims jwtClaims = jwtConsumer.processToClaims(encodedAccessToken); logger.info("JWT validation succeeded! " + jwtClaims); return true; } catch (InvalidJwtException e) { logger.info("Invalid JWT! ", e); return false; } } private JSONObject getDecodedJSONObject(String encodedString){ byte[] decoded = Base64.getDecoder().decode(encodedString); return new JSONObject(new String(decoded)); } }
Hi Kevin - I’m a bit late to this conversation, but I’m working on prototyping a FHIR server with HAPI, and have just begun working with the HSPC reference auth server as an OpenID/OAuth2 solution. While I have followed the documentation to configure and deploy the various components of the HSPC infrastructure (HSPC reference API, etc.) to do end-to-end app testing (including auth flow), my primary interest is in using the HSPC reference auth server along side a custom FHIR server built with HAPI. If I’m understanding your post here correctly, this is a similar approach to the one you’ve taken with NHS Care Connect. Additionally, looking at some of the code in the CCRI, it appears as though the server itself simply extends the HAPI InterceptorAdaptor to inspect bearer tokens (which are assumed to be JWT) and verify authorization conditions based on the token contents, which is more or less in line with what I was imagining and what I’ve heard James speak about in the past.
All that said, I suppose I’m just hoping to verify that you’ve continued to have success using the HSPC reference auth server outside of their overall ‘sandbox’ architecture, and that’s it has been a viable option for integration with your own HAPI-based FHIR server implementation.