Newer
Older
vkid-springsecurity / src / main / java / ru / simplex2 / vkid_spring_security / vk / VkSettings.java
package ru.simplex2.vkid_spring_security.vk;


import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * Значения полей clientId и redirectUri этого класса нужно задать самостоятельно.
 */
public class VkSettings {

    private static final String PKCE_CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
    private static final SecureRandom RANDOM = new SecureRandom();

    /**
     * ID Вашего приложения в VK ID.
     * Узнать ID можно здесь:
     * https://id.vk.com/about/business/go/
     */
    private String clientId;
    /**
     * Uri адрес, по которому VK будет перенаправлять пользователя.
     * Указывается там же, где указан Ваш clientId:
     * https://id.vk.com/about/business/go/
     */
    private String redirectUri;
    private String codeVerifier;

    public VkSettings(String redirectUri, String clientId) {
        this.redirectUri = redirectUri;
        this.clientId = clientId;
    }

    public String generateCodeVerifier() {
        return generateCodeVerifier(64);
    }
    public String generateCodeVerifier(int length) {
        if (length < 43 || length > 128) {
            throw new IllegalArgumentException("code_verifier length must be between 43 and 128");
        }
        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            int idx = RANDOM.nextInt(PKCE_CHARSET.length());
            sb.append(PKCE_CHARSET.charAt(idx));
        }
        return codeVerifier = sb.toString();
    }

    public String generateCodeChallenge(String codeVerifier) {
        if (codeVerifier == null || codeVerifier.isEmpty()) {
            throw new IllegalArgumentException("code_verifier must not be null or empty");
        }
        byte[] bytes = codeVerifier.getBytes(StandardCharsets.US_ASCII);
        byte[] digest = sha256(bytes);
        return Base64.getUrlEncoder().withoutPadding().encodeToString(digest);
    }

    private byte[] sha256(byte[] input) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            return md.digest(input);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("SHA-256 not available", e);
        }
    }

    public String getCodeVerifier() {
        return codeVerifier;
    }

    public void setCodeVerifier(String codeVerifier) {
        this.codeVerifier = codeVerifier;
    }

    public String getClientId() {
        return clientId;
    }

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    public String getRedirectUri() {
        return redirectUri;
    }

    public void setRedirectUri(String redirectUri) {
        this.redirectUri = redirectUri;
    }
}