athenahealth / apiserver-athenaFlex

Software developers can use sample code and documentation to use athenahealth's athenaPractice/athenaFlow FHIR API Server.
https://mydata.athenahealth.com/home
17 stars 7 forks source link

The ID token returned in the Token Response contains an invalid `aud` claim #200

Closed jdkizer9 closed 2 years ago

jdkizer9 commented 3 years ago

Per the OpenID Connect Core Specification ID Token Validation section, item #3 specifies:

The Client MUST validate that the aud (audience) Claim contains its client_id value registered at the Issuer identified by the iss (issuer) Claim as an audience. The aud (audience) Claim MAY contain an array with more than one element. The ID Token MUST be rejected if the ID Token does not list the Client as a valid audience, or if it contains additional audiences not trusted by the Client.

The aud claim in the ID token contains d4e2960e-8201-4f41-a509-8edb791b5562, which is not our client_id. The OAuth library that we are using (AppAuth) performs ID token validation whenever an ID token is returned.

Attempts to not request an ID token results in a server error during the authorization sequence.

JBWEB000065: HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalStateException

JBWEB000309: type JBWEB000066: Exception report

JBWEB000068: message Request processing failed; nested exception is java.lang.IllegalStateException

JBWEB000069: description JBWEB000145: The server encountered an internal error that prevented it from fulfilling this request.

JBWEB000070: exception

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
    com.gehcit.util.DebugLoggingFilter.doFilter(DebugLoggingFilter.java:187)

JBWEB000071: root cause

java.lang.IllegalStateException
    org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:420)
    com.gehcit.fhir.security.controllers.OAuth2SecurityController.authorizeCallback(OAuth2SecurityController.java:367)
    sun.reflect.GeneratedMethodAccessor306.invoke(Unknown Source)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:498)
    org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
    com.gehcit.util.DebugLoggingFilter.doFilter(DebugLoggingFilter.java:187)

Expected behavior would be both of the following:

  1. Add the ability for authorization to work without requesting an ID token
  2. When a client requests an ID token, return a valid ID token
Torin-Shepard-athena commented 3 years ago

@jdkizer9 Please see issue #157.

We have been notified any SMART on FHIR app should be able to call FHIR Server authorize endpoint with only code as value for response_type parameter.

CPS 12.3, CEMR 9.12, athenaPractice and athenaFlow V20 FHIR Server incorrectly requires both code and id_token for response_type parameter. Part of the reason for this is that we use id_token from Microsoft AAD to get the identity of the authenticated user.

The V22 release will include changes so id_token is optional in response_type parameter. Until then, with earlier versions, you must specify response_type=code%20id_token when invoking FHIR Server authorize endpoint.

With regard to the contents of id_token: In current products, the id_token comes directly from Microsoft AAD which sets audience claim to an appropriate Azure Application ID.

With the new regulatory requirement to support fhirUser claim, the V22 release aP/aF FHIR Servers will issue its own id tokens with audience claim set to the requested client id registered at the Dev Portal.

With earlier versions, would it be possible to implement extra logic to work around the issue with AppAuth-Android failing to validate the id_tokens issued by AAD?

jdkizer9 commented 3 years ago

Thanks @Torin-Shepard-athena. I'll look into a work around. In the meantime, do you have a sense for when V22 will be available?

AjeetYadav07 commented 2 years ago

@jdkizer9 v22 will available by June 2022.

AjeetYadav07 commented 2 years ago

@jdkizer9 Since we did not receive any further query in past one month to address as part of this issue, marking as closed.