Discussion

For simple client-side authentication, we provide a minimal Javascript library hosted by Stack Exchange. To add this library to your site, add:

<script type='text/javascript' src='https://api.stackexchange.com/js/2.0/all.js'></script>

Your application must have the client side OAuth flow enabled, and must not have the desktop application redirect uri disabled. Both of these settings are available on an applications edit page.

Usage

The Stack Exchange provided javascript library is intentionally small and minimalistic. If you're looking for simple client side authentication it will probably meet your needs, for more fully featured libraries see Stack Apps.

While this library's flow is mostly standard OAuth 2.0, there are a few non-standard behaviors to enable cross-domain communication. Code that relies on those behaviors not documented as part of the standard authentication flow should not be incorporated into applications or libraries, these are considered implementation details and may be changed at any time.

Initialization

Initialize the library prior to making any other calls with a call to SE.init(options)

<script type='text/javascript'>
SE.init({
    clientId: 1,
    key: '123456',
    channelUrl: 'http://example.com/blank',
    complete: function (data) { ... }
});
</script>

These options are all required:

  • clientId – an application's client id, as indicated on the application edit page
  • key – an application's request key, as indicated on the application edit page
  • channelUrl – a blank page under the same domain as the including page.
  • complete – a function(data) that will be called when initialization is complete

channelUrl is used for cross-domain communication in older browsers, and should be a completely blank, fast loading page.

complete will lose any special blessings with regards to being able to open windows or similar.

An object is passed of the form:

{ version: 'some-unique-string' }

version is provided for bug reporting purposes, few client's will use it during normal operation.

Authentication

Get an access token for (and optionally the identity of) a user with a call to SE.authenticate(options). This method should only be called in response to user action (like clicking a button), lest the popup window created as a result be hidden by the user's browser.

<script type='text/javascript'>
SE.authenticate({
    success: function(data) { ... },
    error: function(data) { ... },
    scope: ['read_inbox'],
    networkUsers: true
});
</script>

Valid options are:

  • success (required) – a function(data) that is called upon a successful authentication
  • error (optional) – a function(data) that is called upon a failed authentication
  • scope (optional) – an array of scopes to request during authentication, valid scopes are in the authentication documentation.
  • networkUsers (optional) – if present and true, a user's associated users will be passed to success.

success is called with an object of the form:

{ accessToken: '12345',
expirationDate: new Date(...),
networkUsers: [...] }

If a scope of no_expiry was requested, expirationDate will not be set.

If networkUsers was not passed to SE.authenticate networkUsers will not be set, if set it is an array of network_user objects.

error is called with an object of the form:

{ errorName: 'access_denied',
errorMessage: 'the unicorns are not amused' }

Possible errors encountered during authentication are documented here, while those encountered during subsequent data fetches are documented here.

Of special note, a user denying access to their account via the Reject button will result in error being called with an errorName of "access_denied".

Be aware that there is no guarantee that either success or error will be called as a result of calling SE.authenticate(...). A user could close the popup window, navigate away, or otherwise interrupt the authentication process in ways that cannot be gracefully reported.

Example

<script type='text/javascript'>
// For simplicity, we're using jQuery for some things
//   However, the library has no jQuery dependency
$(function(){
// Initialize library
SE.init({ 
    // Parameters obtained by registering an app, these are specific to the SE
    //   documentation site
    clientId: 1, 
    key: 'U4DMV*8nvpm3EOpvf69Rxw((', 
    // Used for cross domain communication, it will be validated
    channelUrl: 'https://api.stackexchange.com/docs/proxy',
    // Called when all initialization is finished
    complete: function(data) { 
        $('#login-button')
            .removeAttr('disabled')
            .text('Run Example With Version '+data.version); 
    }
});

// Attach click handler to login button
$('#login-button').on('click', function() {

    // Make the authentication call, note that being in an onclick handler
    //   is important; most browsers will hide windows opened without a
    //   'click blessing'
    SE.authenticate({
        success: function(data) { 
            alert(
                'User Authorized with account id = ' + 
                data.networkUsers[0].account_id + ', got access token = ' + 
                data.accessToken
            ); 
        },
        error: function(data) { 
            alert('An error occurred:\n' + data.errorName + '\n' + data.errorMessage); 
        },
        networkUsers: true
    });
});
});
</script>