(Quick Reference)

Vkontakte Authentication for Spring Security - Reference Documentation

Authors: Pavel Burov

Version: 1.0

1 Introduction

Grails plugin for Vkontakte Authentication, as extension to Grails Spring Security Core plugin.

Requirements:

  • grails 2.0+
  • spring-security-core plugin 2.0-RC2
  • jquery (for Open API authorization)

Links:

2 Installation

Add dependency into BuildConfig.groovy:

plugins {
        compile "org.grails.plugins:spring-security-vkontakte:1.0"
        // …
        // you need to have spring-security-core plugin installed
        // …
    }

Call (optionaly) configuration wizards by:

grails s2-quickstart //configure Spring Security Core
grails s2-init-vkontakte //configure Spring Security Vkontakte

Or you can edit Config.groovy instead and put your Vkontakte App appId/secret and domain class configuration into Config.groovy:

grails.plugin.springsecurity.vkontakte.appId = ..
grails.plugin.springsecurity.vkontakte.secret = ..
grails.plugin.springsecurity.vkontakte.domain.className = 'com.company.VkontakteUser'

It's very basic configuration, for other options (see Configuration section)

Follow Basic Usage guide for full example.

3 Usage

Example app

You can take a look at Example Application, it's very basic app, that shows how to use the plugin. Just clone it, put your Vkontakte App credentials, and play with the code.

Usage

Setup Vkontakte credentials

Put your Vkontakte App appId/secret into Config.groovy:

grails.plugin.springsecurity.vkontakte.appId = ..
grails.plugin.springsecurity.vkontakte.secret = ..

Create domain class for your user

Like domain/VkontakteUser.groovy:

class VkontakteUser {
    Long vkId
    String accessToken
    Date accessTokenExpires

static belongsTo = [user: User] // connected to main Spring Security domain

static constraints = { vkId unique: true } }

The plugin is configured for VkontakteUser class name by default. But you could use different name (or use package) for domain class, for example com.company.UserWithVkontakte, that you should configure at Config.groovy at this case:

grails.plugin.springsecurity.vkontakte.domain.className = 'com.company.VkontakteUser'

Put SignIn with Vkontakte button:

Add into your GSP:

<vkontakteAuth:connect />

Use Spring Security

Now you could use all security tools provided by Spring Security Core.

For example, you could use taglib for checking user state:

<sec:ifLoggedIn>
    <div class="message">Authenticated</div>
    Hello <sec:username/>!
</sec:ifLoggedIn>

<sec:ifNotLoggedIn> <div class="message">Not authenticated</div> <vkontakteAuth:connect /> </sec:ifNotLoggedIn>

4 Configuration

Basic Configuration

Make sure that you have installed and configured spring-security-core plugin before this step.

Calling 'grails s2-init-vkontakte' will make default configuration of plugin for you, make sure that you have configuration in your Config.groovy like:

grails.plugin.springsecurity.vkontakte.domain.className = '<your VkontakteUser domain>'
grails.plugin.springsecurity.vkontakte.appId = '<Vkontakte appId>'
grails.plugin.springsecurity.vkontakte.secret = '<Vkontakte secret>'

Or you can skip 'grails s2-init-vkontakte' step, and make such configuration by yourself.

When you have valid configuration you can put Vkontakte Connect button in you GSP:

<vkontakteAuth:connect />

Vkontakte configuration

NameDefault Value
grails.plugin.springsecurity.vkontakte.appIdmust be specified
grails.plugin.springsecurity.vkontakte.secretmust be specified

Permissions

NameDefault Value
grails.plugin.springsecurity.vkontakte.permissions

See: Vkontakte App permissions

Domain configuration

NameDefault Value
grails.plugin.springsecurity.vkontakte.domain.classNameVkontakteUser
grails.plugin.springsecurity.vkontakte.domain.userConnectionPropertyNameuser
grails.plugin.springsecurity.vkontakte.domain.userIdPropertyNamevkId

Where:

  • .classname - domain class name that will be used for authentication
  • .connectionPropertyName - name of property that connects (belongsTo) to main app user (if you have two different domains, one for app user, one for Vkontakte user)
  • .userIdPropertyName - name of property to hold Vkontakte user id

Authentication configuration

NameDefault Value
grails.plugin.springsecurity.vkontakte.autoCreate.enabledtrue
grails.plugin.springsecurity.vkontakte.autoCreate.roles'ROLE_USER', 'ROLE_VKONTAKTE'

Where:

  • .autoCreate.enabled - plugin will automatically create corresponding user for each new visitor authentication using Vkontakte
  • .autoCreate.roles - default list of roles that will be assigned to create user

Filters configuration

Redirect

NameDefault Value
grails.plugin.springsecurity.vkontakte.filters.redirect.processUrl'/j_spring_security_vkontakte_check'
grails.plugin.springsecurity.vkontakte.filters.redirect.positionSecurityFilterPosition.OPENID_FILTER.order + 1
grails.plugin.springsecurity.vkontakte.filters.redirect.authenticationSuccessHandler''
grails.plugin.springsecurity.vkontakte.filters.redirect.authenticationFailureHandler''
grails.plugin.springsecurity.vkontakte.filters.redirect.successHandler{}
grails.plugin.springsecurity.vkontakte.filters.redirect.failureHandler{}

Where:

  • .filters.redirect.processUrl - url that will be used for authentication
  • .filters.redirect.position - filter position
  • .filters.redirect.authenticationSuccessHandler - bean name to use as authentication successHandler
  • .filters.redirect.authenticationFailureHandler - bean name to use as authentication FailureHandler
  • .filters.redirect.successHandler - configuration for predefined handler
  • .filters.redirect.failureHandler - configuration for predefined handler

Open API

NameDefault Value
grails.plugin.springsecurity.vkontakte.filters.openApi.processUrl'/j_spring_security_vkontakte_open_api_check'
grails.plugin.springsecurity.vkontakte.filters.openApi.positionSecurityFilterPosition.OPENID_FILTER.order + 2
grails.plugin.springsecurity.vkontakte.filters.openApi.authenticationSuccessHandler''
grails.plugin.springsecurity.vkontakte.filters.openApi.authenticationFailureHandler''

Where:

  • .filters.openApi.processUrl - url that will be used for authentication
  • .filters.openApi.position - filter position
  • .filters.openApi.authenticationSuccessHandler - bean name to use as authentication successHandler
  • .filters.openApi.authenticationFailureHandler - bean name to use as authentication FailureHandler

5 Using VkontakteAuthService

How it works

If you want to add some specific logic to default plugin behaviour, you have to create your own service called 'vkontakteAuthService'. Then the plugin will check for known methods of this service, and if they're exist - use them instead of or in additional to own method.

It's some kind of extending an abstract class, but you don't need to create all methods, just what you need.

Used objects:

  • <VkontakteUser> - domain class for your vkontakte user. It's your own class, can have other name, it's just a example
  • <Person> - general user, used by Spring Security. It's your own class, can have other name, it's just a example
  • VkontakteAuthToken - token provided by plugin (instance of com.burig.grails.springsecurity.vkontakte.VkontakteAuthToken)

VkontakteAuthToken contains:

  • String code
  • VkontakteAccessToken accessToken
    • Long userId
    • String accessToken
    • Date expireAt

Notice that <VkontakteUser> and <Person> can be same object, or can be two different object (with a relation), depends on your architecture.

Take a look at sources

To understand how it works, and which methods you can use for customization. Take a look at sources of DefaultVkontakteAuthDao

List of possible methods:

<VkontakteUser> findUser(VkontakteAuthToken token)

Called when vkontakte user is authenticated (on every request), must return existing instance for specified token, if exits. If doesn't - return null.

<VkontakteUser> create(VkontakteAuthToken token)

Called when we have a new vkontakte user, called on first login to create all required data structures.

Notice, that if you have such method, it replaces all other methods for user creation, like:

  • createAppUser
  • prepopulateAppUser
  • onCreate
  • afterCreate
  • createRoles

<Person> createAppUser(<VkontakteUser> user, VkontakteAuthToken token)

Called if you have configured two domains, one for main user, one for vkontakte user.

void afterCreate(<VkontakteUser> user, VkontakteAuthToken token)

Called after user was created by plugin, just after saving into database, but before roles are assigned to user. You can setup user object with some extra values. If you need to access Vkontakte API, you could use token, it contains 'accessToken' for current user.

void createRoles(<VkontakteUser> user)

Called when we have a new Vkontakte user, called on first login to create roles list for new user. If method doesn't exist, user will be created with default roles (configured at 'grails.plugins.springsecurity.vkontakte.autoCreate.roles')

void updateToken(<VkontakteUser> user, VkontakteAuthToken token)

Called on each login, you could update user details if needed.

<Person> getAppUser(<VkontakteUser> user)

Must return object to store in security context for specified vkontakte user (can return itself)

Object getPrincipal(<Person> person)

Principal to use with Spring Security. It's very useful if it will be instance of UserDetails class.

Collection<GrantedAuthority> getRoles(<Person> user)

Must return roles list for specified vkontakte user

6 Common Issues

Enable logging

If you have troubles with plugin, please enabled logging, so you can see what's happening:

log4j = {
    debug 'com.burig'
}

Authentication don't work with localhost domain

Make sure that you're using a real domain name for your application. Not a localhost, and avoid .local domains as well.

You can make a fake domain like dev.myapp.com, by putting into /etc/hosts the following line:

127.0.0.1 dev.myapp.com
If you already have line starting with 127.0.0.1, just add your dev.myapp.com at the end of the line.

See more details about hosts file, and location of the file for different operation systems see: hosts (file)

After that, you should configure your Grails app to use this domain, by adding following line into Config.groovy. Of course, you need to use this domain only for development, so put this configuration into development environment config:

environments {
    development {
        grails.serverURL = "http://dev.myapp.com:${System.getProperty('server.port', '8080')}/${appName}"
    }
}