io.stallion.users.OAuthApprovalController.java Source code

Java tutorial

Introduction

Here is the source code for io.stallion.users.OAuthApprovalController.java

Source

/*
 * Stallion Core: A Modern Web Framework
 *
 * Copyright (C) 2015 - 2016 Stallion Software LLC.
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation, either version 2 of
 * the License, or (at your option) any later version. This program is distributed in the hope that
 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
 * License for more details. You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
 *
 *
 *
 */

package io.stallion.users;

import io.stallion.Context;
import io.stallion.dataAccess.DataAccessRegistry;
import io.stallion.dataAccess.DataAccessRegistration;
import io.stallion.dataAccess.LocalMemoryStash;
import io.stallion.dataAccess.NoStash;
import io.stallion.dataAccess.StandardModelController;
import io.stallion.dataAccess.db.DB;
import io.stallion.dataAccess.db.DbPersister;
import io.stallion.exceptions.ClientException;
import io.stallion.requests.StRequest;
import io.stallion.settings.Settings;
import io.stallion.utils.Encrypter;
import io.stallion.utils.GeneralUtils;
import io.stallion.utils.json.JSON;
import org.apache.commons.lang3.StringUtils;

import java.util.Set;

import static io.stallion.utils.Literals.*;

public class OAuthApprovalController extends StandardModelController<OAuthApproval> {

    public static void register() {
        DataAccessRegistration registration = new DataAccessRegistration().setBucket("oauth_approvals")
                .setControllerClass(OAuthApprovalController.class).setModelClass(OAuthApproval.class);
        if (DB.available()) {
            registration.setStashClass(NoStash.class).setTableName("oauth_approvals")
                    .setPersisterClass(DbPersister.class);
        } else {
            registration.setStashClass(LocalMemoryStash.class).setPath("oauth_approvals").setShouldWatch(false);

        }

    }

    public static OAuthApprovalController instance() {
        return (OAuthApprovalController) DataAccessRegistry.instance().get("oauth_approvals");
    }

    public boolean checkHeaderAndAuthorizeUserForRequest(StRequest request) {
        String header = request.getHeader("Authorization");
        if (empty(header)) {
            return false;
        }
        if (!header.startsWith("Bearer ")) {
            return false;
        }
        String token = header.substring(7);
        OAuthUserLogin login = tokenToUser(token);
        Context.getRequest().setScoped(login.isScoped());
        Context.getRequest().setScopes(login.getScopes());
        Context.setUser(login.getUser());
        return true;
    }

    public OAuthUserLogin tokenToUser(String accessToken) {
        return tokenToUser(accessToken, false);
    }

    public OAuthUserLogin tokenToUser(String accessToken, boolean ignoreExpires) {
        if (!accessToken.contains("-")) {
            throw new ClientException("Invalid access token format");
        }
        String[] parts = StringUtils.split(accessToken, "-", 2);
        if (!StringUtils.isNumeric(parts[0])) {
            throw new ClientException("Invalid access token format");
        }
        long userId = Long.parseLong(parts[0]);
        IUser user = UserController.instance().forId(userId);
        if (user == null) {
            throw new ClientException("User not found for access token");
        }
        String decrypted = Encrypter.decryptString(user.getEncryptionSecret(), parts[1]);
        OAuthAccesTokenData data = JSON.parse(decrypted, OAuthAccesTokenData.class);
        if (data.getUserId() != userId) {
            throw new ClientException("Invalid access token");
        }
        if (!ignoreExpires && data.getExpires() < mils()) {
            throw new ClientException("Access token has expired");
        }
        if (Settings.instance().getoAuth().getAlwaysCheckAccessTokenValid()) {
            OAuthApproval approval = OAuthApprovalController.instance().forId(data.getApprovalId());
            if (approval == null || approval.isRevoked()
                    || (!ignoreExpires && approval.getAccessTokenExpiresAt() < mils())) {
                throw new ClientException("Invalid approval");
            }
        }
        OAuthUserLogin login = new OAuthUserLogin().setScoped(data.isScoped()).setUser(user)
                .setApprovalId(data.getApprovalId()).setScopes(data.getScopes());
        return login;
    }

    public OAuthApproval checkGrantApprovalForUser(GrantType grantType, IUser user, String fullClientId,
            Set<String> scopes, boolean isScoped, String redirectUri) {
        return checkGrantApprovalForUser(grantType, user, fullClientId, scopes, isScoped, "");
    }

    public OAuthApproval checkGrantApprovalForUser(GrantType grantType, IUser user, String fullClientId,
            Set<String> scopes, boolean isScoped, String redirectUri, String providedCode) {
        if (emptyInstance(user) || !user.isAuthorized() || empty(user.getId())) {
            throw new ClientException("You are not logged in with a valid user.");
        }

        OAuthClient client = OAuthClientController.instance().clientForFullId(fullClientId);

        if (emptyInstance(client) || client.getFullClientId().equals(fullClientId) || client.isDisabled()
                || client.getDeleted()) {
            throw new ClientException("Invalid client id");
        }
        if (!client.hasGrantType(grantType)) {
            throw new ClientException("Cannot use this grant type with this client");
        }
        if (!client.getAllowedRedirectUris().contains(redirectUri)) {
            throw new ClientException("Unauthorized redirect_uri");
        }
        if (!isScoped) {
            if (client.isScoped()) {
                throw new ClientException("This client requires specific scopes.");
            }
        } else if (client.isScoped() && !client.getScopes().containsAll(scopes)) {
            throw new ClientException("Invalid set of scopes for this client application.");
        }
        return generateNewApprovalForUser(user, client, scopes, isScoped, providedCode);
    }

    public OAuthApproval generateNewApprovalForUser(IUser user, OAuthClient client, Set<String> scopes,
            boolean isScoped) {
        return generateNewApprovalForUser(user, client, scopes, isScoped, "");
    }

    public OAuthApproval generateNewApprovalForUser(IUser user, OAuthClient client, Set<String> scopes,
            boolean isScoped, String providedCode) {
        OAuthApproval approval = new OAuthApproval();
        approval.setId(Context.dal().getTickets().nextId());
        if (empty(providedCode) || !client.isAllowProvidedCode()) {
            approval.setCode(approval.getId() + "-" + GeneralUtils.secureRandomToken(30));
        } else {
            approval.setCode(providedCode);
        }
        approval.setCreatedAt(mils());
        approval.setVerified(false);
        approval.setInternalSecret(GeneralUtils.secureRandomToken(30));
        approval.setScopes(or(scopes, set()));
        approval.setScoped(isScoped);
        return createOrUpdateApproval(approval, user, client);
    }

    protected OAuthApproval createOrUpdateApproval(OAuthApproval approval, IUser user, OAuthClient client) {

        approval.setRefreshToken(GeneralUtils.secureRandomToken(30));

        if (!approval.isScoped() && client.isScoped()) {
            throw new ClientException("You must set specific scopes for this approval");
        } else if (approval.isScoped()) {
            if (!client.getScopes().containsAll(approval.getScopes())) {
                throw new ClientException("This client cannot grant the given scopes");
            }
        }

        approval.setAccessTokenExpiresAt(mils() + (or(client.getAccessTokenValiditySeconds(),
                Settings.instance().getoAuth().getAccessTokenValidSeconds()) * 1000));
        approval.setRefreshTokenExpiresAt(mils() + (or(client.getRefreshTokenValiditySeconds(),
                Settings.instance().getoAuth().getRefreshTokenValidSeconds()) * 1000));

        OAuthAccesTokenData tokenData = new OAuthAccesTokenData().setExpires(approval.getAccessTokenExpiresAt())
                .setUserId(user.getId()).setApprovalId(approval.getId()).setClientId(client.getId())
                .setScoped(approval.isScoped()).setScopes(approval.getScopes());

        String token = user.getId() + "-"
                + Encrypter.encryptString(user.getEncryptionSecret(), JSON.stringify(tokenData));
        approval.setAccessToken(token);
        approval.setUserId(user.getId());
        approval.setClientId(client.getFullClientId());
        save(approval);
        return approval;
    }

    public OAuthApproval newAccessTokenForRefreshToken(String refreshToken, String accessToken, String fullClientId,
            String fullClientSecret) {
        OAuthClient client = OAuthClientController.instance().clientForFullId(fullClientId);
        if (client.getClientSecret().equals(fullClientSecret)) {
            throw new ClientException("Invalid client secret");
        }
        OAuthUserLogin login = tokenToUser(accessToken, true);
        OAuthApproval approval = forId(login.getApprovalId());
        if (approval.isRevoked()) {
            throw new ClientException("Approval has been revoked. You will need to re-authorize");
        }
        if (!refreshToken.equals(approval.getRefreshToken())) {
            throw new ClientException("Invalid refresh token");
        }
        return createOrUpdateApproval(approval, login.getUser(), client);
    }

}