github.com/phrase/openapi@v0.0.0-20240514140800-49e8a106740e/openapi-generator/templates/java/libraries/jersey2-experimental/auth/HttpSignatureAuth.mustache (about)

     1  {{>licenseInfo}}
     2    
     3  package {{invokerPackage}}.auth;
     4  
     5  import {{invokerPackage}}.Pair;
     6  import {{invokerPackage}}.ApiException;
     7  
     8  import java.net.URI;
     9  import java.net.URLEncoder;
    10  import java.security.MessageDigest;
    11  import java.security.Key;
    12  import java.text.SimpleDateFormat;
    13  import java.util.ArrayList;
    14  import java.util.Base64;
    15  import java.util.Date;
    16  import java.util.Locale;
    17  import java.util.Map;
    18  import java.util.List;
    19  
    20  import org.tomitribe.auth.signatures.*;
    21  
    22  /**
    23   * A Configuration object for the HTTP message signature security scheme.
    24   */
    25  public class HttpSignatureAuth implements Authentication {
    26  
    27    private Signer signer;
    28  
    29    // An opaque string that the server can use to look up the component they need to validate the signature.
    30    private String keyId;
    31  
    32    // The HTTP signature algorithm.
    33    private Algorithm algorithm;
    34  
    35    // The list of HTTP headers that should be included in the HTTP signature.
    36    private List<String> headers;
    37  
    38    // The digest algorithm which is used to calculate a cryptographic digest of the HTTP request body.
    39    private String digestAlgorithm;
    40  
    41    /**
    42     * Construct a new HTTP signature auth configuration object.
    43     *
    44     * @param keyId An opaque string that the server can use to look up the component they need to validate the signature.
    45     * @param algorithm The signature algorithm.
    46     * @param headers The list of HTTP headers that should be included in the HTTP signature.
    47     */
    48    public HttpSignatureAuth(String keyId, Algorithm algorithm, List<String> headers) {
    49      this.keyId = keyId;
    50      this.algorithm = algorithm;
    51      this.headers = headers;
    52      this.digestAlgorithm = "SHA-256";
    53    }
    54  
    55    /**
    56     * Returns the opaque string that the server can use to look up the component they need to validate the signature.
    57     *
    58     * @return The keyId.
    59     */
    60    public String getKeyId() {
    61      return keyId;
    62    }
    63  
    64    /**
    65     * Set the HTTP signature key id.
    66     *
    67     * @param keyId An opaque string that the server can use to look up the component they need to validate the signature.
    68     */
    69    public void setKeyId(String keyId) {
    70      this.keyId = keyId;
    71    }
    72  
    73    /**
    74     * Returns the HTTP signature algorithm which is used to sign HTTP requests.
    75     */
    76    public Algorithm getAlgorithm() {
    77      return algorithm;
    78    }
    79  
    80    /**
    81     * Sets the HTTP signature algorithm which is used to sign HTTP requests.
    82     *
    83     * @param algorithm The HTTP signature algorithm.
    84     */
    85    public void setAlgorithm(Algorithm algorithm) {
    86      this.algorithm = algorithm;
    87    }
    88  
    89    /**
    90     * Returns the digest algorithm which is used to calculate a cryptographic digest of the HTTP request body.
    91     *
    92     * @see java.security.MessageDigest
    93     */
    94    public String getDigestAlgorithm() {
    95      return digestAlgorithm;
    96    }
    97  
    98    /**
    99     * Sets the digest algorithm which is used to calculate a cryptographic digest of the HTTP request body.
   100     *
   101     * The exact list of supported digest algorithms depends on the installed security providers.
   102     * Every implementation of the Java platform is required to support "MD5", "SHA-1" and "SHA-256".
   103     * Do not use "MD5" and "SHA-1", they are vulnerable to multiple known attacks.
   104     * By default, "SHA-256" is used.
   105     *
   106     * @param digestAlgorithm The digest algorithm.
   107     *
   108     * @see java.security.MessageDigest
   109     */
   110    public void setDigestAlgorithm(String digestAlgorithm) {
   111      this.digestAlgorithm = digestAlgorithm;
   112    }
   113  
   114    /**
   115     * Returns the list of HTTP headers that should be included in the HTTP signature.
   116     */
   117    public List<String> getHeaders() {
   118      return headers;
   119    }
   120  
   121    /**
   122     * Sets the list of HTTP headers that should be included in the HTTP signature.
   123     *
   124     * @param headers The HTTP headers.
   125     */
   126    public void setHeaders(List<String> headers) {
   127      this.headers = headers;
   128    }
   129  
   130    public Signer getSigner() {
   131      return signer;
   132    }
   133  
   134    public void setSigner(Signer signer) {
   135      this.signer = signer;
   136    }
   137  
   138    /**
   139     * Set the private key used to sign HTTP requests using the HTTP signature scheme.
   140     *
   141     * @param key The private key.
   142     */
   143    public void setPrivateKey(Key key) throws ApiException {
   144      if (key == null) {
   145        throw new ApiException("Private key (java.security.Key) cannot be null");
   146      }
   147  
   148      signer = new Signer(key, new Signature(keyId, algorithm, null, headers));
   149    }
   150  
   151    @Override
   152    public void applyToParams(List<Pair> queryParams, Map<String, String> headerParams, Map<String, String> cookieParams,
   153                              String payload, String method, URI uri) throws ApiException {
   154      try {
   155        if (headers.contains("host")) {
   156          headerParams.put("host", uri.getHost());
   157        }
   158  
   159        if (headers.contains("date")) {
   160          headerParams.put("date", new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US).format(new Date()));
   161        }
   162  
   163        if (headers.contains("digest")) {
   164          headerParams.put("digest",
   165            this.digestAlgorithm + "=" +
   166              new String(Base64.getEncoder().encode(MessageDigest.getInstance(this.digestAlgorithm).digest(payload.getBytes()))));
   167        }
   168  
   169        if (signer == null) {
   170          throw new ApiException("Signer cannot be null. Please call the method `setPrivateKey` to set it up correctly");
   171        }
   172  
   173        // construct the path with the URL query string
   174        String path = uri.getPath();
   175  
   176        List<String> urlQueries = new ArrayList<String>();
   177        for (Pair queryParam : queryParams) {
   178          urlQueries.add(queryParam.getName() + "=" + URLEncoder.encode(queryParam.getValue(), "utf8").replaceAll("\\+", "%20"));
   179        }
   180  
   181        if (!urlQueries.isEmpty()) {
   182          path = path + "?" + String.join("&", urlQueries);
   183        }
   184  
   185        headerParams.put("Authorization", signer.sign(method, path, headerParams).toString());
   186      } catch (Exception ex) {
   187        throw new ApiException("Failed to create signature in the HTTP request header: " + ex.toString());
   188      }
   189    }
   190  }