Provide 'silent' token-renewal support
Provide 'silent' token-renewal support

Silent renewal of tokens is achieved by the dynamic construction of a
child iframe that attempts to re-authenticate the page  with the same
original arguments as the 'parent' page, but with an additional prompt=none
argument.  If this successfully responds with a token we update the token
we're sending for API calls to this renewed value, otherwise we sign-out.

The specific details of how this is achieved within this plugin are mildly
complex so i'll describe them here.

Parent lifetime:
  If the parent receives an 'oauth2:authSuccess' event and the directive has
  been configured to support silenttokenrenewal (by specifying the
  silentTokenRedirectUrl parameter on the directive)  then it will call the
  'renewTokenSilently' method on the endpoint.  This code then sets a timeout
  to fire a minute before the token is expected to expire.  When the timeout
  is triggered some code executes that constructs a hidden iframe that calls
  out to the Identity Server's authorization endpoint with a prompt=none
  argument set, and an associated 5 second timeout to cleanup if the IDP does
  not respond within that timeframe. It also registers a listener for
  postMessage calls.  If the listener is triggered with some data of the
  string 'oauth2.silentRenewFailure' then it will broadcast the event
  'oauth2:authExpired' otherwise it will attempt to use the passed data
  as the location hash that would've been returned from the IDP, so the normal
  event broadcasing occurs (this should re-emit an 'oauth2:authSuccess' and restart
  the scheduled silent renewal again.)

Child iframe lifetime:
  Firstly this directive adds a new route 'silent-renew' to the route provider
  which has no template or controller, but as it is within the same template
  as the original oauth directive was nested we get to re-leverage the existing
  oauth configuration.  This means when setting up your OIDC client in your IP
  you will need to support at least two redirects, one for the outer-page (the
  existing routes) and a new one for the hidden inner frame
  (probably <scheme>://<host>/#/silent-renew).

  When requests come back in to the 'silent-renew' page they are treated as normal
  'post authentication' requests and the location is parsed as usual, if an
  'oauth2:authSuccess' event is emitted and capture by the child iframe then
  it will use 'postMessage' to send the silently-renewed token hash back to the
  parent frame, otherwise if an 'oauth2:authError' is captured by the child iframe
  then it will use 'postMessage' to send the string 'oauth2.silentRenewFailure'
  to the parent window.

JamesRandall/AngularJS-OAuth2