Usage — Velruse 1.1 documentation

### Navigation

- index
- modules |
- next |
- previous |
- Velruse 1.1 documentation »

# Usage

Velruse is built around the Pyramid web framework. Each provider is implemented as a Pyramid addon via Pyramid’s `include` mechanism. This means that it is very easy to integrate Velruse with a Pyramid application directly. When operating outside of Pyramid, Velruse contains a full WSGI Pyramid app that can be run via any WSGI server. The app exposes an HTTP API which speaks language-agnostic JSON. This allows the Velruse app to run independently of the rest of your web stack.

Warning

In order to get working code examples, many providers require that the callback that is configured at the end of the authentication workflow must be a fully qualified, externally resolvable domain name.

## As a Service

Velruse will run as a standalone web application which has an API that makes it easy to authenticate with various providers, as well as obtain user credentials and profile information after a user has already been authenticated. This allows virtually anyone to use Velruse, regardless of their chosen language or framework. The standalone app is a standard Pyramid application, so if you are familiar with the framework, you will feel right at home. We are going to assume you have no experience with Pyramid just to be safe though.

The first thing we need to do is provide the Velruse application with some information about our account details for each provider we are supporting. Namely the consumer key and consumer secret of our app. These two values can be obtained by creating an application on each of the provider’s websites, commonly found in the “developers” section. Once you have obtained a consumer key and secret from each of the providers you wish to support, we need to tell Velruse about them. This can be done by creating an .ini file that will be used to serve the standalone app. It could look something like the following:

    [server:main]
    use = egg:waitress
    host = 0.0.0.0
    port = 80

    [app:velruse]
    use = egg:velruse

    setup = myapp.setup_velruse

    endpoint = http://example.com/logged_in

    store = redis
    store.host = localhost
    store.port = 6379
    store.db = 0
    store.key_prefix = velruse_ustore

    provider.facebook.consumer_key = KMfXjzsA2qVUcnnRn3vpnwWZ2pwPRFZdb
    provider.facebook.consumer_secret = ULZ6PkJbsqw2GxZWCIbOEBZdkrb9XwgXNjRy
    provider.facebook.scope = email

    provider.tw.impl = twitter
    provider.tw.consumer_key = ULZ6PkJbsqw2GxZWCIbOEBZdkrb9XwgXNjRy
    provider.tw.consumer_secret = eoCrFwnpBWXjbim5dyG6EP7HzjhQzFsMAcQOEK

Ok so that’s a lot of stuff. Let’s go through each section. The values in the ‘[server:main]’ section are saying that we want to serve our app via the Waitress web server, to bind to any ip address, and to run on port 80. Next, we have a number of configuration options for our web app. The important ones are as follows:

`setup`
  A Python dotted-name describing the location of a callable. This callable must accept a Pyramid `Configurator` object and use it to initialize a session factory as well as a backend storage mechanism.
`endpoint`
  The url that velruse will redirect to after it finishes authenticating with a provider.
`store`
  The type of cache that you would like velruse to use. We’ve selected Redis but this could be any storage backend supported by the anykeystore library.
`store.*`
  The parameters within the store are dependent on the backend selected. See the anykeystore documentation for more details.
`provider.*`
  The parameters for a specific provider. The format is `provider.<identifier>.<setting>` where `identifier` should be the shorthand name of one of the providers. The `identifier` can be anything, but if it is not the name of a provider then `provider.<identifier>.impl` must point to something. This allows you to configure multiple endpoints using the same provider (e.g. maybe one endpoint for login only, and another for authorization later).

Finally, we define all of the provider-specific consumer keys and secrets that we talked about earlier. Reference each provider’s page for documentation on the supported settings.

Once we are done configuring the application, we can serve it by running:

    pserve example.ini

This will start serving Velruse at the specified IP and port in your INI file. We can then communicate with the app, by sending HTTP requests to that IP/port. The API is quite simple, and it only consists of the following two routes:

`/{provider}/login`
  Authenticates with a provider, and redirects back to the url specified by the endpoint setting.
`/auth_info?format=json&token={token}`
  Obtains the profile and credential information for a user with the specified token.

Warning

The `/auth_info` URL should be considered sensitive and only trusted services should be allowed access. If an attacker intercepts a an authentication token, they could potentially query `/auth_info` and learn all of the credentials for the user.

### Initiating a Login Attempt

In order to get a user to begin the Velruse authentication workflow we need to have the user submit a POST request to the provider’s login URL. This can be done by submitting a form placed on some page within your site. An example of such a form is given below.

    <form action="/velruse/login/facebook" method="post">
        <input type="hidden" name="scope" value="publish_stream,create_event" />
        <input type="submit" value="Login with Facebook" />
    </form>

### Handling a Login Attempt

After completing the provider’s authentication process, Velruse will then redirect to your endpoint using a POST request, with the token assigned to a user stored in the form data. This token can be used to obtain authentication details about the user. An example of how to obtain the token in the endpoint view of an application is given below.

    # sample callback view in flask
    @app.route('/logged_in', methods=['POST'])
    def login_callback():
        # token is stored in the form data
        token = request.form['token']
        return render_template('result.html', result=token)

As you can see, the token is stored in the form data of the request. We can then use the `/velruse/auth_info` route to obtain a user’s authentication details. So if we were passed a token with a value of `'t0k3n'`, then we can access everything Velruse knows about that user by visiting `'/velruse/auth_info?format=json&token=t0k3n'`. We can further add to our previous example to make such a call.

    # sample callback view in flask
    @app.route('/logged_in', methods=['POST'])
    def login_callback():
        token = request.form['token']

        # the request must contain 'format' and 'token' params
        payload = {'format': 'json', 'token': token}
        # sending a GET request to /auth_info
        response = requests.get(request.host_url + 'velruse/auth_info', params=payload)
        auth_info = response.json
        return render_template('result.html', result=auth_info)

This example is using the Requests library. `auth_info` contains information about the user’s login attempt. In all cases the response will contain `provider_name` and `provider_type` metadata. If the response was successful then the `profile` and `credentials` will be available. In the case of a failure, the `error` will be available to explain what may have gone wrong.

## As a Pyramid Plugin

The standalone Velruse application is simply a Pyramid application that is configured using Velruse’s Pyramid plugin. To use Velruse in your own Pyramid applications you simply have to include the providers you want in your configuration:

    config.include('velruse.providers.facebook')
    config.add_facebook_login_from_settings(prefix='velruse.facebook.')

Much like the standalone app, we need to provide Velruse with some information about our account details for each provider we are supporting. Namely the consumer key and consumer secret of our app. This information can be obtained by creating an application on each of the provider’s websites, commonly found in the “developers” section. Once you have obtained credentials for your application (usually a consumer key and secret) from each of the providers you wish to support, we need to tell Velruse about them. We can easily do this by adding them to our app’s INI files. You can use the following example as a guide:

    velruse.facebook.consumer_key = 411326239420890
    velruse.facebook.consumer_secret = 81ef2318a1999tttc6d9c43d4e93be0c
    velruse.facebook.scope = email

    velruse.twitter.consumer_key = ULZ6PkJbeqwgGxZaCIbdEBZekrbgXwgXajRl
    velruse.twitter.consumer_secret = eoCrewnpdWXjfim5ayGgEPeHzjcQzFsqAchOEa

### Initiating a Login Attempt

After Velruse is included in your app, you can easily generate a login url for any particular provider. This is accomplished by calling the `velruse.login_url()` like so:

    login_url(request, 'twitter')

In this case, `velruse.login_url()` will generate a url like `http://www.example.com/login/twitter`. A user can then be directed to that url when they need to authenticate through the Twitter provider. This is commonly done in the form of a link or a button on the login page of your app.

In order to get a user to begin the Velruse authentication workflow we need to have the user submit a POST request to the provider’s login URL. This can be done by submitting a form placed on some page within your site. An example of such a form is given below.

    <form action="${login_url(request, 'twitter')}" method="post">
        <input type="submit" value="Login with Twitter" />
    </form>

### Handling a Login Attempt

By integrating your application directly with Velruse, the workflow for handling a login attempt is more efficient. Instead of having to talk back to the standalone application, the credentials are available directly within your app without requiring any external storage. Once the user has visited the URL generated by `velruse.login_url()`, they will be redirected to the respective provider. The provider will eventually redirect the user back to the callback URL. Velruse can then perform validation of the results and generate the profile. You must then specify Pyramid views that will be invoked when authentication was completed or denied. The first view we need to add is called when authentication succeeds, and could potentially look something like this:

    @view_config(
        context='velruse.AuthenticationComplete',
        renderer='myapp:templates/result.mako',
    )
    def login_complete_view(request):
        context = request.context
        result = {
            'provider_type': context.provider_type,
            'provider_name': context.provider_name,
            'profile': context.profile,
            'credentials': context.credentials,
        }
        return {
            'result': json.dumps(result, indent=4),
        }

The important thing to note here, is that we need to register a view that has a value of `velruse.AuthenticationComplete` assigned to the context predicate. This results in the `login_complete_view` being invoked when a third party redirects to your app and was successful. This view will most likely be used to store credentials, create accounts, and redirect the user to the rest of your application.

If you want to create a view that is only called when a specific third party’s authentication succeeds, you can change the view configuration to specify a more specific context:

    @view_config(
        context='velruse.providers.facebook.FacebookAuthenticationComplete',
        renderer='myapp:templates/result.mako',
    )
    def fb_login_complete_view(request):
        pass

It is possible to create many views. Only the most specific view will be invoked for the matching provider.

The second view we need to add is called when authentication fails:

    @view_config(
        context='velruse.AuthenticationDenied',
        renderer='myapp:templates/result.mako',
    )
    def login_denied_view(request):
        return {
            'result': 'denied',
        }

We assign a value of `velruse.AuthenticationDenied` to the context predicate of the view. The `login_denied_view` will be invoked when a third party redirects to your app and reports a failed authentication. This view will most likely be used to display an appropriate error message and redirect the user. After Velruse is configured in your Pyramid application, login urls are generated for each of the providers that you want to support, and the previous two views are defined, you can effectively use Velruse to authenticate with third party providers.

### Navigation

- index
- modules |
- next |
- previous |
- Velruse 1.1 documentation »