4.5.3.1. Social Login в REST API

Механизм авторизации через социальные сети, или social login, также можно использовать в REST API. Исходный код приложения, описанного в этом примере, доступен на GitHub, а сам пример описан в разделе Social Login. Ниже приведены ключевые моменты этого примера, позволяющие получить OAuth-токен через аккаунт Facebook.

  1. Создайте пакет restapi в корневом каталоге модуля web и поместите в него собственный контроллер Spring MVC. Контроллер должен содержать два основных метода: get(), возвращающий ResponseEntity, и login(), в котором мы будем получать OAuth-токен.

    @RequestMapping(method = RequestMethod.GET)
    public ResponseEntity get() {
        String loginUrl = getAsPrivilegedUser(() ->
                facebookService.getLoginUrl(getAppUrl(), OAuth2ResponseType.CODE_TOKEN)
        );
    
        HttpHeaders headers = new HttpHeaders();
        headers.set(HttpHeaders.LOCATION, loginUrl);
        return new ResponseEntity<>(headers, HttpStatus.FOUND);
    }

    Здесь мы проверяем переданный код Facebook, получаем код доступа и издаём токен с помощью OAuthTokenIssuer:

    @RequestMapping(method = RequestMethod.POST, value = "login")
    public ResponseEntity<OAuth2AccessToken> login(@RequestParam("code") String code) {
        User user = getAsPrivilegedUser(() -> {
            FacebookUserData userData = facebookService.getUserData(getAppUrl(), code);
    
            return socialRegistrationService.findOrRegisterUser(
                userData.getId(), userData.getEmail(), userData.getName());
        });
    
        OAuth2AccessTokenResult tokenResult = oAuthTokenIssuer.issueToken(user.getLogin(),
                messageTools.getDefaultLocale(), Collections.emptyMap());
    
        HttpHeaders headers = new HttpHeaders();
        headers.set(HttpHeaders.CACHE_CONTROL, "no-store");
        headers.set(HttpHeaders.PRAGMA, "no-cache");
        return new ResponseEntity<>(tokenResult.getAccessToken(), headers, HttpStatus.OK);
    }
  2. Исключите пакет restapi из сканирования в модулях web/core: это необходимо, так как бин OAuthTokenIssuer доступен только внутри контекста REST API, и сканирование его в контексте приложения будет вызывать ошибку.

    <context:component-scan base-package="com.company.demo">
        <context:exclude-filter type="regex" expression="com\.company\.demo\.restapi\..*"/>
    </context:component-scan>
  3. Создайте файл facebook-login-demo.html в каталоге проекта modules/web/web/VAADIN. Он будет содержать JavaScript-код, выполняющийся на HTML-странице:

    <html>
    <head>
        <title>Facebook login demo with REST-API</title>
        <script src="jquery-3.2.1.min.js"></script>
        <style type="text/css">
     #users { display: none; }
        </style>
    </head>
    <body>
    <h1>Facebook login demo with REST-API</h1>
    
    <script type="application/javascript"...>
    </script>
    
    <a id="fbLink" href="/app/rest/facebook">Login with Facebook</a>
    
    <div id="users">
        You are logged in!
    
        <h1>Users</h1>
    
        <div id="usersList">
        </div>
    </div>
    
    </body>
    </html>

    В этом скрипте мы попробуем залогиниться через Facebook. Сначала удаляем лишний код из URL, затем передаём код в REST API для получения OAuth-токена, и в случае успешной аутентификации мы сможем загружать и сохранять данные как обычно:

    var oauth2Token = null;
    
    function tryToLoginWithFacebook() {
        var urlHash = window.location.hash;
    
        if (urlHash && urlHash.indexOf('&code=') >= 0) {
            console.log("Try to login to CUBA REST-API!");
    
            var urlCode = urlHash.substring(urlHash.indexOf('&code=') + '&code='.length);
            console.log("Facebook code: " + urlCode);
    
            history.pushState("", document.title, window.location.pathname);
    
            $.post({
                url: '/app/rest/facebook/login',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded'
                },
                dataType: 'json',
                data: {code: urlCode},
                success: function (data) {
                    oauth2Token = data.access_token;
    
                    loadUsers();
                }
            })
        }
    }
    
    function loadUsers() {
        $.get({
            url: '/app/rest/v2/entities/sec$User?view=_local',
            headers: {
                'Authorization': 'Bearer ' + oauth2Token,
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            success: function (data) {
                $('#fbLink').hide();
                $('#users').show();
    
                $.each(data, function (i, user) {
                    $('#usersList').append("<li>" + user.name + " (" + user.email + ")</li>");
                });
            }
        });
    }
    
    tryToLoginWithFacebook();

    Другой пример использования JavaScript-кода в приложениях CUBA вы можете найти в разделе Пример использования из JavaScript.