/// <summary> /// Converts the error message into its wire format. /// </summary> /// <param name="message">The error message.</param> /// <returns>The serilized form of the error. </returns> string GetErrorString(ResourceAccessErrorResponse message) { string errorString; string headerFirstElementFormat = " {0}=\"{1}\""; string headerFormat = ", {0}=\"{1}\""; errorString = OAuthConstants.AuthenticationType; errorString += string.Format(CultureInfo.InvariantCulture, headerFirstElementFormat, OAuthConstants.Realm, message.Realm); errorString += string.Format(CultureInfo.InvariantCulture, headerFormat, OAuthConstants.Error, message.ErrorCode); if (message.ErrorDescription != null) { errorString += string.Format(CultureInfo.InvariantCulture, headerFormat, OAuthConstants.ErrorDescription, message.ErrorDescription); } if (message.ErrorUri != null) { errorString += string.Format(CultureInfo.InvariantCulture, headerFormat, OAuthConstants.ErrorUri, message.ErrorUri.ToString()); } if (message.Scope != null) { errorString += string.Format(CultureInfo.InvariantCulture, headerFormat, OAuthConstants.Scope, message.Scope); } return(errorString); }
/// <summary> /// Handle the HTTP pipeline EndRequest event. This sends an error message back if nay errors have occured in the processing pipeline. /// </summary> /// <param name="sender">Sender of this event.</param> /// <param name="args">Event arguments.</param> internal void OnEndRequest(object sender, EventArgs args) { if ((HttpContext.Current.Items[errorMessageIdentifier] != null) && (HttpContext.Current.Items[errorMessageIdentifier] is ResourceAccessErrorResponse)) { ResourceAccessErrorResponse message = HttpContext.Current.Items[errorMessageIdentifier] as ResourceAccessErrorResponse; SendErrorResponse(message, HttpContext.Current); } }
/// <summary> /// This method parses the incoming token and validates it. /// </summary> /// <param name="accessToken">The incoming access token.</param> /// <param name="error">This out paramter is set if any error occurs.</param> /// <returns>True on success, False on error.</returns> protected bool ReadAndValidateToken(string accessToken, string key, out ResourceAccessErrorResponse error) { bool tokenValid = false; error = null; SecurityToken token = null; ClaimsIdentityCollection claimsIdentityCollection = null; try { SimpleWebTokenHandler handler = new SimpleWebTokenHandler(); // read the token token = handler.ReadToken(accessToken); // validate the token claimsIdentityCollection = handler.ValidateToken(token, key); // create a claims Principal from the token IClaimsPrincipal authenticatedClaimsPrincipal = ServiceConfiguration.ClaimsAuthenticationManager.Authenticate( HttpContext.Current.Request.Url.AbsoluteUri, new ClaimsPrincipal(claimsIdentityCollection)); if (authenticatedClaimsPrincipal != null) { tokenValid = true; // Set the ClaimsPrincipal so that it is accessible to the application SetPrincipal(authenticatedClaimsPrincipal); } } catch (InvalidTokenReceivedException ex) { error = new ResourceAccessErrorResponse(OAuthConfiguration.Configuration.ServiceSettings.Realm.ToString(), ex.ErrorCode, ex.ErrorDescription); } catch (ExpiredTokenReceivedException ex) { error = new ResourceAccessErrorResponse(OAuthConfiguration.Configuration.ServiceSettings.Realm.ToString(), ex.ErrorCode, ex.ErrorDescription); } catch (Exception ex) { error = new ResourceAccessErrorResponse(OAuthConfiguration.Configuration.ServiceSettings.Realm.ToString(), OAuthConstants.ErrorCode.InvalidToken, "Token validation failed: " + ex.Message); } return(tokenValid); }
/// <summary> /// Handle the HTTP pipeline AuthenticateRequest event, after ensuring that the module has been initialized. /// </summary> /// <param name="sender">Sender of this event.</param> /// <param name="args">Event arguments.</param> internal void OnAuthenticateRequest(object sender, EventArgs args) { HttpContext context = HttpContext.Current; ResourceAccessErrorResponse error; string accessToken; // checks if it is an OAuth Request and gets the access token if (TryReadAccessToken(context.Request, out accessToken)) { // Parses the token and validates it. if (!ReadAndValidateToken(accessToken, OAuthConfiguration.Configuration.StsSettings.SymmetricKey, out error)) { context.Items.Add(errorMessageIdentifier, error); } } else { error = new ResourceAccessErrorResponse(OAuthConfiguration.Configuration.ServiceSettings.Realm.ToString(), OAuthConstants.ErrorCode.UnauthorizedClient, "UnauthorizedClient"); context.Items.Add(errorMessageIdentifier, error); } }
/// <summary> /// Serializes the error message and sends it in response to the incoming request. /// </summary> /// <param name="errorMessage">The OAuth error message.</param> /// <param name="context">The curent application <see cref="HttpContext"/>.</param> public void SendErrorResponse(ResourceAccessErrorResponse errorMessage, HttpContext context) { if (errorMessage == null) { throw new ArgumentNullException("errorMessage"); } if (context == null) { throw new ArgumentNullException("context"); } HttpResponse response = context.Response; if (errorMessage.ErrorCode == null) { throw new ArgumentNullException("errorMessage.ErrorCode"); } // set the appropriate status code if (errorMessage.ErrorCode == OAuthConstants.ErrorCode.InsufficientScope) { response.StatusCode = (int)HttpStatusCode.Forbidden; } else if (errorMessage.ErrorCode == OAuthConstants.ErrorCode.InvalidRequest) { response.StatusCode = (int)HttpStatusCode.BadRequest; } else { response.StatusCode = (int)HttpStatusCode.Unauthorized; } string errorHeader = GetErrorString(errorMessage); //response.Headers.Add("WWW-Authenticate", errorHeader); response.AddHeader("WWW-Authenticate", errorHeader); response.End(); }
/// <summary> /// Converts the error message into its wire format. /// </summary> /// <param name="message">The error message.</param> /// <returns>The serilized form of the error. </returns> string GetErrorString(ResourceAccessErrorResponse message) { string errorString; string headerFirstElementFormat = " {0}=\"{1}\""; string headerFormat = ", {0}=\"{1}\""; errorString = OAuthConstants.AuthenticationType; errorString += string.Format(CultureInfo.InvariantCulture, headerFirstElementFormat, OAuthConstants.Realm, message.Realm); errorString += string.Format( CultureInfo.InvariantCulture, headerFormat, OAuthConstants.Error, message.ErrorCode ); if (message.ErrorDescription != null) { errorString += string.Format( CultureInfo.InvariantCulture, headerFormat, OAuthConstants.ErrorDescription, message.ErrorDescription ); } if (message.ErrorUri != null) { errorString += string.Format( CultureInfo.InvariantCulture, headerFormat, OAuthConstants.ErrorUri, message.ErrorUri.ToString() ); } if (message.Scope != null) { errorString += string.Format( CultureInfo.InvariantCulture, headerFormat, OAuthConstants.Scope, message.Scope ); } return errorString; }
/// <summary> /// Serializes the error message and sends it in response to the incoming request. /// </summary> /// <param name="errorMessage">The OAuth error message.</param> /// <param name="context">The curent application <see cref="HttpContext"/>.</param> public void SendErrorResponse(ResourceAccessErrorResponse errorMessage, HttpContext context) { if (errorMessage == null) { throw new ArgumentNullException("errorMessage"); } if (context == null) { throw new ArgumentNullException("context"); } HttpResponse response = context.Response; if (errorMessage.ErrorCode == null) { throw new ArgumentNullException( "errorMessage.ErrorCode" ); } // set the appropriate status code if (errorMessage.ErrorCode == OAuthConstants.ErrorCode.InsufficientScope) { response.StatusCode = (int)HttpStatusCode.Forbidden; } else if (errorMessage.ErrorCode == OAuthConstants.ErrorCode.InvalidRequest) { response.StatusCode = (int)HttpStatusCode.BadRequest; } else { response.StatusCode = (int)HttpStatusCode.Unauthorized; } string errorHeader = GetErrorString(errorMessage); //response.Headers.Add("WWW-Authenticate", errorHeader); response.AddHeader("WWW-Authenticate", errorHeader); response.End(); }
/// <summary> /// This method parses the incoming token and validates it. /// </summary> /// <param name="accessToken">The incoming access token.</param> /// <param name="error">This out paramter is set if any error occurs.</param> /// <returns>True on success, False on error.</returns> protected bool ReadAndValidateToken( string accessToken, string key, out ResourceAccessErrorResponse error ) { bool tokenValid = false; error = null; SecurityToken token = null; ClaimsIdentityCollection claimsIdentityCollection = null; try { SimpleWebTokenHandler handler = new SimpleWebTokenHandler(); // read the token token = handler.ReadToken( accessToken ); // validate the token claimsIdentityCollection = handler.ValidateToken( token, key ); // create a claims Principal from the token IClaimsPrincipal authenticatedClaimsPrincipal = ServiceConfiguration.ClaimsAuthenticationManager.Authenticate( HttpContext.Current.Request.Url.AbsoluteUri, new ClaimsPrincipal( claimsIdentityCollection ) ); if ( authenticatedClaimsPrincipal != null ) { tokenValid = true; // Set the ClaimsPrincipal so that it is accessible to the application SetPrincipal( authenticatedClaimsPrincipal ); } } catch ( InvalidTokenReceivedException ex ) { error = new ResourceAccessErrorResponse(OAuthConfiguration.Configuration.ServiceSettings.Realm.ToString(), ex.ErrorCode, ex.ErrorDescription ); } catch ( ExpiredTokenReceivedException ex ) { error = new ResourceAccessErrorResponse(OAuthConfiguration.Configuration.ServiceSettings.Realm.ToString(), ex.ErrorCode, ex.ErrorDescription); } catch ( Exception ex) { error = new ResourceAccessErrorResponse(OAuthConfiguration.Configuration.ServiceSettings.Realm.ToString(), OAuthConstants.ErrorCode.InvalidToken, "Token validation failed: " + ex.Message); } return tokenValid; }