Chapter 2. Service Providers

2.1. OAuth2 service providers

OAuth 2 is rapidly becoming a preferred authorization protocol, and is used by major service providers such as Facebook and Github.
In Spring.NET Social, an IOAuth2ServiceProvider<T> instance is used to establish connections with a OAuth2-based service provider:

public interface IOAuth2ServiceProvider<T> : IServiceProvider<T> where T : IApiBinding
{
  IOAuth2Operations OAuthOperations { get; }

  T GetApi(string accessToken);
}

OAuthOperations property returns an API to use to conduct the authorization flow, or "OAuth Dance", with a service provider.
The result of this flow is an AccessGrant that can be used to obtain a strongly-typed binding to the ServiceProvider's API by calling GetApi.

The IOAuth2Operations interface is shown below:

public interface IOAuth2Operations
{ 
  string BuildAuthorizeUrl(GrantType grantType, OAuth2Parameters parameters);

  string BuildAuthenticateUrl(GrantType grantType, OAuth2Parameters parameters);

  AccessGrant ExchangeForAccess(string authorizationCode, string redirectUri, NameValueCollection additionalParameters);

  AccessGrant RefreshAccess(string refreshToken, string scope, NameValueCollection additionalParameters);
}

Callers are first expected to call BuildAuthorizeUrl(GrantType, OAuth2Parameters) to construct the URL to redirect the user to for connection authorization.
Upon user authorization, the authorizationCode returned by the provider should be exchanged for an AccessGrant. The AccessGrant should then used to get the ServiceProvider API.
This flow is illustrated below:

As you can see, there is a back-and-forth conversation that takes place between the application and the service provider to grant the application access to the provider account.
This exchange, commonly known as the "OAuth Dance", follows these steps:

  1. The flow starts by the application redirecting the user to the provider's authorization URL.
    Here the provider displays a web page asking the user if he or she wishes to grant the application access to read and update their data.

  2. The user agrees to grant the application access.

  3. The service provider redirects the user back to the application (via the redirect URI), passing an authorization code as a parameter.

  4. The application exchanges the authorization code for an access grant.

  5. The service provider issues the access grant to the application.
    The grant includes an access token and a refresh token.
    One receipt of these tokens, the "OAuth dance" is complete.

  6. The application uses the AccessGrant to establish a connection between the local user account and the external provider account.
    With the connection established, the application can now obtain a reference to the Service API and invoke the provider on behalf of the user.

The example code below shows use of a GitHubServiceProvider to create a connection to GitHub using the OAuth2 server-side flow illustrated above.
Here, GitHubServiceProvider implements IOAuth1ServiceProvider<IGitHub>:

GitHubServiceProvider serviceProvider = new GitHubServiceProvider("clientId", "clientSecret");
IOAuth2Operations oauthOperations = serviceProvider.OAuthOperations;
OAuth2Parameters parameters = new OAuth2Parameters();
parameters.RedirectUri = "https://my-callback-url";
string authorizeUrl = oauthOperations.BuildAuthorizeUrl(GrantType.AuthorizationCode, parameters);
Response.Redirect(authorizeUrl);

// upon receiving the callback from the provider:
AccessGrant accessGrant = oauthOperations.ExchangeForAccess(authorizationCode, "https://my-callback-url", null);
IGitHub gitHubApi = serviceProvider.GetApi(accessGrant);

The following example illustrates the client-side "implicit" authorization flow also supported by OAuth2.
The difference between this flow and the server-side "authorization code" flow above is the provider callback directly contains the access grant (no additional exchange is necessary).
This flow is appropriate for clients incapable of keeping the access grant credentials confidential, such as a mobile device or JavaScript-based user agent.

GitHubServiceProvider serviceProvider = new GitHubServiceProvider("clientId", "clientSecret");
IOAuth2Operations oauthOperations = serviceProvider.OAuthOperations;
OAuth2Parameters parameters = new OAuth2Parameters();
parameters.RedirectUri = "https://my-callback-url";
string authorizeUrl = oauthOperations.BuildAuthorizeUrl(GrantType.ImplicitGrant, parameters);
Response.Redirect(authorizeUrl);

// upon receiving the callback from the provider:
AccessGrant accessGrant = new AccessGrant(accessToken);
IGitHub gitHubApi = serviceProvider.GetApi(accessGrant);

2.2. OAuth1 service providers

OAuth 1 is the previous version of the OAuth protocol. It is more complex than OAuth 2, and sufficiently different that it is supported separately. Twitter, Linked In, and TripIt are some of the well-known ServiceProviders that use OAuth 1.
In Spring.NET Social, an IOAuth1ServiceProvider<T> instance is used to establish connections with a OAuth1-based service provider:
public interface IOAuth1ServiceProvider<T> : IServiceProvider<T> where T : IApiBinding
{
  IOAuth1Operations OAuthOperations { get; }

  T GetApi(string accessToken, string secret);
}

Like a OAuth2-based provider, OAuthOperations returns an API to use to conduct the authorization flow, or "OAuth Dance".
The result of the OAuth 1 flow is an OAuthToken that can be used to obtain a strongly-typed binding to the ServiceProvider's API by calling GetApi.

The OAuth1Operations interface is shown below:

public interface OAuth1Operations 
{
  OAuth1Version Version { get; }

  OAuthToken FetchRequestToken(String callbackUrl, NameValueCollection additionalParameters);

  string BuildAuthorizeUrl(string requestToken, OAuth1Parameters parameters);

  string BuildAuthenticateUrl(string requestToken, OAuth1Parameters parameters);

  OAuthToken ExchangeForAccessToken(AuthorizedRequestToken requestToken, NameValueCollection additionalParameters);
}

Callers are first expected to call fetchNewRequestToken(String) to obtain a temporary token from the ServiceProvider to use during the authorization session.
Next, callers should call BuildAuthorizeUrl(string, OAuth1Parameters) to construct the URL to redirect the user to for connection authorization.
Upon user authorization, the authorized request token returned by the provider should be exchanged for an access token. The access token should then used to get the ServiceProvider API.
This flow is illustrated below:

  1. The flow starts with the application asking for a request token.
    The purpose of the request token is to obtain user approval and it can only be used to obtain an access token.
    In OAuth 1.0a, the consumer callback URL is passed to the provider when asking for a request token.

  2. The service provider issues a request token to the consumer.

  3. The application redirects the user to the provider's authorization page, passing the request token as a parameter.
    In OAuth 1.0, the callback URL is also passed as a parameter in this step.

  4. The service provider prompts the user to authorize the consumer application and the user agrees.

  5. The service provider redirects the user's browser back to the application (via the callback URL).
    In OAuth 1.0a, this redirect includes a verifier code as a parameter. At this point, the request token is authorized.

  6. The application exchanges the authorized request token (including the verifier in OAuth 1.0a) for an access token.

  7. The service provider issues an access token to the consumer. The "dance" is now complete.

  8. The application uses the access token to establish a connection between the local user account and the external provider account.
    With the connection established, the application can now obtain a reference to the Service API and invoke the provider on behalf of the user.

The example code below shows use of a TwitterServiceProvider to create a connection to Twitter using the OAuth1 server-side flow illustrated above.
Here, TwitterServiceProvider implements IOAuth1ServiceProvider<ITwitter>:

TwitterServiceProvider serviceProvider = new TwitterServiceProvider("consumerKey", "consumerSecret");
OAuth1Operations oauthOperations = serviceProvider.AuthOperations;
OAuthToken requestToken = oauthOperations.FetchRequestToken("https://my-callback-url", null);
string authorizeUrl = oauthOperations.BuildAuthorizeUrl(requestToken, null);
Response.Redirect(authorizeUrl);

// upon receiving the callback from the provider:
OAuthToken accessToken = oauthOperations.ExchangeForAccessToken(new AuthorizedRequestToken(requestToken, oauthVerifier), null);
ITwitter twitterApi = serviceProvider.GetApi(accessToken.Value, accessToken.Secret);