Documentation

Docs / Development / OAuth in sensenet

OAuth in sensenet

OAuth 2.0 is the industry-standard protocol for authorization. In sensenet we use it as an extension to our web token authentication to let users authenticate using well-known services (such as Google or Facebook).

The benefit is that users are able to sign in to a sensenet application with a single click, without manual registration.

How it works?

When new users come to the site, they will be able to sign in by clicking the Google or Facebook button (or a similar custom experience implemented by the developer). The workflow is the following:

From that point on the user will be able to use the application as a regular user.

Configuration

You can specify where new users are created and their content type using the OAuth settings content in the usual global Settings folder.

{
   UserType: "User",
   Domain: "Public"
}

New users are created under the domain above separated into organizational units named by the provider.

OAuth providers

A sensenet OAuth provider is a small plugin that is designed to verify a token using a particular service. Out of the box we offer the following OAuth provider for sensenet:

These providers are available as nuget packages on the server side and npm packages on the client. Please follow the instructions in the nuget readme, these packages usually involve executing an install command before you can use them.

Custom OAuth provider

The OAuth provider feature is extendable by design, so developers may create a custom provider for any 3rd party service by implementing a simple api. For detailed explanation of the api elements to implement please refer to the source code documentation.

public class CustomOAuthProvider : OAuthProvider
{
    public override string IdentifierFieldName { get; } = "CustomUserId";
    public override string ProviderName { get; } = "myservicename";

    public override IOAuthIdentity GetUserData(object tokenData)
    {
        return tokenData as OAuthIdentity;
    }

    public override string VerifyToken(HttpRequestBase request, out object tokenData)
    {
        dynamic userData;

        try
        {
            userData = GetUserDataFromToken(request);
        }
        catch (Exception)
        {
            throw new InvalidOperationException("OAuth error: cannot parse user data from the request.");
        }

        tokenData = new OAuthIdentity
        {
            Identifier = userData.sub,
            Email = userData.email,
            Username = userData.sub,
            FullName = userData.name
        };

        return userData.sub;
    }

    private static dynamic GetUserDataFromToken(HttpRequestBase request)
    {
        string body;
        using (var reader = new StreamReader(request.InputStream))
        {
            body = reader.ReadToEnd();
        }

        dynamic requestBody = JsonConvert.DeserializeObject(body);
        string token = requestBody.token;

        //TODO: verify token and extract basic user data
        // return userData        
    }
}

The example above assumes that there is a field on the User content type called CustomUserId. Registering this field is the responsibility of the provider install process.

To start using your custom provider you only have to add a reference to your provider library and sensenet will automatically discover and register your class.

Client api

If you are using the JavaScript client SDK (as it is recommended), you do not have to deal with sending OAuth tokens to the server, it will do it for you.

REST api

As an alternative, you can use the native REST api when authenticating with a 3rd party OAuth service. After receiving the service-specific token, that token has to be sent to the server for verification. The api is the following:

/sn-oauth/login?provider=providername

For example:

$.ajax({
    url: "/sn-oauth/login?provider=google",
    dataType: "json",
    type: 'POST',
    data: JSON.stringify({ 'token':id_token }),
    success: function () {
        console.log('Success');
    }
});

Is something missing? See something that needs fixing? Propose a change here.