OAuth 2.0 CTP 1.4 sample and ACS passive federation

Unanswered OAuth 2.0 CTP 1.4 sample and ACS passive federation

  • Thursday, June 02, 2011 2:18 PM
     
     

    I have been looking the OAuth CTP 1.4 sample (https://connect.microsoft.com/site1168/Downloads). It comes tantalisingly close to demonstrating how to use ACS to passively federate a protected resource as follows...

     

    1. Client tries to access protected resource (e.g. a xap file)

    2. Client is routed to ACS to pick an identity provider (IP) to authenticate against.

    3. Client picks proprietary IP-STS or Google etc..

    4. Client authenticates with IP.

    5. IP redirects to ACS where claims are transformed.

    6. ACS issues SWT token to the client and re-directs to the protected resource using the configured relying party Return URL.

     

    I was able to implement the outlined scenario by replacing the AuthorizationServer in the sample with another website which I federated with ACS via metadata. After updating SamplesConfiguration.EndUserLoginUrl to point at this new site WIF/ACS took over and I was able to use the IPs configured for my relying party to authorize access to the protected resource.

     

    However the only way to get the OAuth token following successful authentication was to add a custom RequestValidator to the WebClient and manually shred the SignInResponseMessage to extract the BinarySecurityToken.  However in bypassing OAuthClientSettings.RequestingAccessToken, OAuthClientSettings.AccessTokenReceived and OAuthClientSettings.EndUserAuthorizationFailed in the sample I have lost the OAuth refresh token.

     

    Firstly, is there a sample which demonstrates how to obtain an ACS refresh token? And secondly, how can I use Microsoft.IdentityModel.Protocols.OAuth.Client.OAuthClient to request a new token with the refresh token?

     

    Thanks

     

    Don


    • Edited by vu1garis Thursday, June 02, 2011 2:20 PM Typo
    •  

All Replies

  • Friday, June 03, 2011 9:59 AM
     
     
  • Friday, June 03, 2011 10:42 AM
     
     

    Thanks for the response...

     

    However, in Allen's reply his demonstration of how to use the refreshToken is predicated upon being able to get hold of the refresh token in the first place! In the 1.4 CTP sample this is achieved by storing the refresh token in the session via OAuthClientSettings.AccessTokenReceived and subsequently retrieving the value from the session when making use of the token (as Allen's post demonstrates). My issue arises as a consequence of routing the OAuth client infrastructure (the code in Global.asax.cs Application_Start) to a website which has been federated with ACS; OAuthClientSettings no longer raises the AccessTokenReceived event. Instead ACS is redirecting to the Return URL I have defined in the relying party after authentication and the only way I have found to access the resulting token is by injecting a custom System.Web.Util.RequestValidator and intercepting the resulting Microsoft.IdentityModel.Protocols.WSFederation.SignInResponseMessage. At this point there is no access to the refresh token...

     

    Looking at Allen's disassembly it would seem possible to hand crank an AccessTokenRequestWithRefreshToken

     

    AccessTokenRequestWithRefreshToken tokenRequest = new AccessTokenRequestWithRefreshToken(oauthCreds.TokenUri);

                tokenRequest.ClientId = serverEntry.ClientId;

                tokenRequest.ClientSecret = serverEntry.ClientSecret;

                tokenRequest.RefreshToken = oauthCreds.RefreshToken;

                RequestingAccessTokenEventArgs accessTokenEventArgs = new RequestingAccessTokenEventArgs(HttpContext.Current, tokenRequest, null);

                OAuthClientSettings.OnRequestingAccessToken(this, accessTokenEventArgs);

                OAuthMessage message = OAuthClient.GetAccessToken(accessTokenEventArgs.AccessTokenRequest);

                oauthCreds.LastRefreshTime = DateTime.UtcNow;

                AccessTokenResponse authzResponse = message as AccessTokenResponse;

     

    However without values for ClientId, ClientSecret and crucially RefreshToken I don't see how this could be a solution. One solution would be to extend the life of the token to  ACS's current 24hr maximum (http://msdn.microsoft.com/en-us/library/gg185906.aspx) but this is just a nasty hack and would require custom logic to invalidate tokens within the 24hr lifetime if you wanted to deny access to a user who had acquired a 24hr token.

  • Tuesday, June 07, 2011 3:12 AM
    Moderator
     
     

    Hi,

    WS-Federation and OAuth are different protocols. It seems the Refresh Token you mentioned in this thread is an OAuth concept. The scenario you want to achieve is WS-Federation (Passive). So I don't quite know what you want to do. If the question is whether you can use Refresh token in a WS-Federation scenario the answer is definitely "no" as it's an OAuth concept.

    Thanks,


    Wengchao Zeng
    Please mark the replies as answers if they help or unmark if not.
    If you have any feedback about my replies, please contact msdnmg@microsoft.com.
    Microsoft One Code Framework
  • Tuesday, June 07, 2011 9:47 AM
     
      Has Code

    Hello,

    Thanks for getting back to me. You're absolutely correct WRT: OAuth and WS-Federation I had somewhat confused myself by adding the federated authorization service. This is totally redundant as we can talk OAuth directly to ACS. For example, If you modify the sample as follows you do not require the AuthorizationServer (or the federated Auth service I added ;-)) to get an SWT token back from ACS.

    public const string EndUserLoginUrl = "https://{YOUR SERVICE NAMESPACE HERE}.accesscontrol.appfabriclabs.com/v2/wsfederation?wa=wsignin1.0&wtrealm={YOUR REALM URL HERE}&wctx=rm=0&id=passive&ru=/WebClient/Default.aspx?response_type=code&redirect_uri=https://localhost/WebClient/Default.aspx";
    

    However if you do this then for some reason the OAuthClientSettings events I alluded earlier do not get invoked. I was wondering if this had anything to do with the behaviour of the OAuthHandler?

     

    <handlers>
      <add name="OAuthHandler" verb="*" path="OAuthHandler.ashx" type="Microsoft.IdentityModel.Protocols.OAuth.Client.EndUserAuthorizationResponseHandler, Microsoft.IdentityModel.Protocols.OAuth"/>
    </handlers>
    

    In any case I have been able to achieve the passive federation outlined in my original post without using the majority of Microsoft.IdentityModel.Protocols.OAuth. My only real concern relates to using a custom RequestValidator with the following web configuration.

     

     <location path="Default.aspx">
      <system.web>
       <authorization>
        <allow users="*" />
       </authorization>
      </system.web>
     </location>
    
     <system.web>
      <httpRuntime requestValidationMode="4.0" requestValidationType="{MY CUSTOM VALIDATOR}"/>
      <authentication mode="None" />
     </system.web>
    
    

    I have completely stripped out the Microsoft.IdentityModel.Protocols.OAuth infrastructure from Global.aspx and Default.aspx now looks something like this

     

        protected void Page_Load( object sender, EventArgs e )
        {
          OAuthCredential creds = GetOAuthCredential(); // as in 1.4 sample
          if (creds != null)
          {
            // redirect to protected resource - a xap file
          }
          else
          {
            // redirect to ACS using a URL similar to the above
          }
        }
    

    I had wanted to add the following to <system.web> however when I do so

     

        <authorization>
          <deny users="?" />
        </authorization>
    

    I get the following...

     

    Access is denied.

     

    Description: An error occurred while accessing the resources required to serve this request. The server may not be configured for access to the requested URL.

    Error message 401.2.: Unauthorized: Logon failed due to server configuration.  Verify that you have permission to view this directory or page based on the credentials you supplied and the authentication methods enabled on the Web server.  Contact the Web server's administrator for additional assistance.

    As you would expect from the above the User Identity is set to an un-authenticated GenericPrincipal. I'm not sure of the best way to fix this. I could construct a ClaimsPrincipal in  RequestValidator but this feels wrong. From a WIF best practice point of view what should I be doing? Introducing a custom Module to take care of this? I know, I know  RTFM ;-) any pointers as to the best place to start would be appreciated.

     

    Regards

     

    Don

     

  • Monday, June 13, 2011 2:46 PM
    Owner
     
     

    From a support perspective this is really beyond what we can do here in the forums. If you cannot determine your answer here or on your own, consider opening a support case with us. Visit this link to see the various support options that are available to better meet your needs:  http://support.microsoft.com/default.aspx?id=fh;en-us;offerprophone.

     

     

     


    --Trevor H.
    Send files to Hotmail.com: "MS_TREVORH"