001/*
002 * Copyright 2024 Emmanuel Bourg
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package net.jsign.jca;
018
019import java.io.IOException;
020import java.security.GeneralSecurityException;
021import java.security.KeyStore;
022import java.security.SecureRandom;
023import java.util.LinkedHashMap;
024import java.util.Map;
025import javax.net.ssl.HttpsURLConnection;
026import javax.net.ssl.KeyManagerFactory;
027import javax.net.ssl.SSLContext;
028
029import net.jsign.KeyStoreBuilder;
030
031/**
032 * Credentials for the Garantir Remote Signing service.
033 *
034 * @since 7.0
035 */
036public class GaraSignCredentials {
037
038    public String username;
039    public String password;
040    public KeyStore.Builder keystore;
041    public String sessionToken;
042
043    public GaraSignCredentials(String username, String password, String keystore, String storepass) {
044        this(username, password, new KeyStoreBuilder().keystore(keystore).storepass(storepass).builder());
045    }
046
047    public GaraSignCredentials(String username, String password, KeyStore.Builder keystore) {
048        this.username = username;
049        this.password = password;
050        this.keystore = keystore;
051    }
052
053    public String getSessionToken(String endpoint) throws IOException {
054        if (sessionToken == null) {
055            RESTClient client = new RESTClient(endpoint)
056                    .authentication((conn, data) -> {
057                        if (conn instanceof HttpsURLConnection && keystore != null) {
058                            try {
059                                KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
060                                kmf.init(keystore.getKeyStore(), ((KeyStore.PasswordProtection) keystore.getProtectionParameter("")).getPassword());
061
062                                SSLContext context = SSLContext.getInstance("TLS");
063                                context.init(kmf.getKeyManagers(), null, new SecureRandom());
064                                ((HttpsURLConnection) conn).setSSLSocketFactory(context.getSocketFactory());
065                            } catch (GeneralSecurityException e) {
066                                throw new RuntimeException("Unable to load the GaraSign client certificate", e);
067                            }
068                        }
069                    });
070
071            Map<String, String> params = new LinkedHashMap<>();
072            params.put("api_version", "1.0");
073            if (username != null && password != null) {
074                params.put("username", username);
075                params.put("password", password);
076            }
077
078            Map<String, ?> response = client.post("/authenticate", params);
079            String status = (String) response.get("status");
080            if (!"SUCCESS".equals(status)) {
081                throw new IOException("Failed to authenticate with GaraSign: " + response.get("message"));
082            }
083            sessionToken = (String) response.get("sessionToken");
084        }
085
086        return sessionToken;
087    }
088}