Class ScramScheme

java.lang.Object
org.apache.hc.client5.http.impl.auth.ScramScheme
All Implemented Interfaces:
AuthScheme

@Contract(threading=UNSAFE) @Experimental public final class ScramScheme extends Object implements AuthScheme
Strict HTTP SCRAM client implementing SCRAM-SHA-256 per RFC 7804 with SCRAM core per RFC 5802/7677.

HTTP SCRAM uses no channel binding (GS2 header "n,,"; c=biws).

Experimental: This API is work in progress and may change without notice in a future release.

Since:
5.6
  • Field Details

    • LOG

      private static final org.slf4j.Logger LOG
    • DEFAULT_WARN_MIN_ITERATIONS

      private static final int DEFAULT_WARN_MIN_ITERATIONS
      See Also:
    • DEFAULT_MAX_ITERATIONS_ALLOWED

      private static final int DEFAULT_MAX_ITERATIONS_ALLOWED
      See Also:
    • GS2_HEADER

      private static final String GS2_HEADER
      See Also:
    • C_BIND_B64

      private static final String C_BIND_B64
      See Also:
    • B64

      private static final Base64.Encoder B64
    • B64D

      private static final Base64.Decoder B64D
    • secureRandom

      private final SecureRandom secureRandom
    • warnMinIterations

      private final int warnMinIterations
    • minIterationsRequired

      private final int minIterationsRequired
    • maxIterationsAllowed

      private final int maxIterationsAllowed
    • state

      private ScramScheme.State state
    • complete

      private boolean complete
    • realm

      private String realm
    • sid

      private String sid
    • username

      private String username
    • password

      private char[] password
    • principal

      private Principal principal
    • clientNonce

      private String clientNonce
    • clientFirstBare

      private String clientFirstBare
    • serverFirstRaw

      private String serverFirstRaw
    • serverNonce

      private String serverNonce
    • salt

      private byte[] salt
    • iterations

      private int iterations
    • expectedV

      private byte[] expectedV
  • Constructor Details

    • ScramScheme

      public ScramScheme()
      Default policy: warn if i < 4096, no hard enforcement; SHA-256 only.
      Since:
      5.6
    • ScramScheme

      public ScramScheme(int warnMinIterations, int minIterationsRequired, SecureRandom rnd)
      Constructor with custom iteration policy.
      Parameters:
      warnMinIterations - warn if iteration count is lower than this (0 disables warnings)
      minIterationsRequired - fail if iteration count is lower than this (0 disables enforcement)
      rnd - optional secure random source (null uses system default)
      Since:
      5.6
    • ScramScheme

      public ScramScheme(int warnMinIterations, int minIterationsRequired, int maxIterationsAllowed, SecureRandom rnd)
      Constructor with custom iteration policy.
      Parameters:
      warnMinIterations - warn if iteration count is lower than this (0 disables warnings)
      minIterationsRequired - fail if iteration count is lower than this (0 disables enforcement)
      maxIterationsAllowed - fail if iteration count is greater than this (must be positive)
      rnd - optional secure random source (null uses system default)
      Since:
      5.6
  • Method Details

    • getName

      public String getName()
      Returns textual designation of the scheme.
      Specified by:
      getName in interface AuthScheme
      Returns:
      the name of the given authentication scheme
      Since:
      5.6
    • isConnectionBased

      public boolean isConnectionBased()
      SCRAM is per-request (no connection binding).
      Specified by:
      isConnectionBased in interface AuthScheme
      Returns:
      true if the scheme is connection based, false if the scheme is request based.
      Since:
      5.6
    • isChallengeExpected

      public boolean isChallengeExpected()
      SCRAM must inspect final responses to verify v= in Authentication-Info.
      Specified by:
      isChallengeExpected in interface AuthScheme
      Returns:
      true if responses with non 401/407 response codes must be processed by the scheme.
      Since:
      5.6
    • processChallenge

      public void processChallenge(AuthChallenge authChallenge, org.apache.hc.core5.http.protocol.HttpContext context) throws MalformedChallengeException
      Specified by:
      processChallenge in interface AuthScheme
      Parameters:
      authChallenge - the auth challenge
      context - HTTP context
      Throws:
      MalformedChallengeException - in case the auth challenge is incomplete, malformed or otherwise invalid.
      Since:
      5.6
      See Also:
    • processChallenge

      public void processChallenge(org.apache.hc.core5.http.HttpHost host, boolean challenged, AuthChallenge authChallenge, org.apache.hc.core5.http.protocol.HttpContext context) throws MalformedChallengeException, AuthenticationException
      Handles 401 challenges (with/without data) and final responses carrying Authentication-Info (any status code).
      Specified by:
      processChallenge in interface AuthScheme
      Parameters:
      host - HTTP host
      challenged - true if the response was unauthorised (401/407)
      authChallenge - the auth challenge or null if no challenge was received
      context - HTTP context
      Throws:
      MalformedChallengeException - in case the auth challenge is incomplete,
      AuthenticationException - in case the authentication process is unsuccessful.
      Since:
      5.6
    • isChallengeComplete

      public boolean isChallengeComplete()
      Description copied from interface: AuthScheme
      Authentication process may involve a series of challenge-response exchanges. This method tests if the authorization process has been fully completed (either successfully or unsuccessfully), that is, all the required authorization challenges have been processed in their entirety.

      Please note if the scheme returns true from this method in response to a challenge, it effectively implies a failure to respond to this challenge and termination of the authentication process.

      Specified by:
      isChallengeComplete in interface AuthScheme
      Returns:
      true if the authentication process has been completed, false otherwise.
      Since:
      5.6
    • getRealm

      public String getRealm()
      Description copied from interface: AuthScheme
      Returns authentication realm. If the concept of an authentication realm is not applicable to the given authentication scheme, returns null.
      Specified by:
      getRealm in interface AuthScheme
      Returns:
      the authentication realm
      Since:
      5.6
    • isResponseReady

      public boolean isResponseReady(org.apache.hc.core5.http.HttpHost host, CredentialsProvider credentialsProvider, org.apache.hc.core5.http.protocol.HttpContext context) throws AuthenticationException
      Allow response when: - INIT (preemptive client-first) — only if creds have been prepared - ANNOUNCED (401 without data) - SERVER_FIRST_RCVD (ready to send client-final)
      Specified by:
      isResponseReady in interface AuthScheme
      Parameters:
      credentialsProvider - The credentials to be used for authentication
      context - HTTP context
      Returns:
      true if an authorization response can be generated and the authentication handshake can proceed, false otherwise.
      Throws:
      AuthenticationException - if authorization string cannot be generated due to an authentication failure
      Since:
      5.6
    • generateAuthResponse

      public String generateAuthResponse(org.apache.hc.core5.http.HttpHost host, org.apache.hc.core5.http.HttpRequest request, org.apache.hc.core5.http.protocol.HttpContext context) throws AuthenticationException
      Description copied from interface: AuthScheme
      Generates an authorization response based on the current state. Some authentication schemes may need to load user credentials required to generate an authorization response from a CredentialsProvider prior to this method call.
      Specified by:
      generateAuthResponse in interface AuthScheme
      Parameters:
      request - The request being authenticated
      context - HTTP context
      Returns:
      authorization header
      Throws:
      AuthenticationException - if authorization string cannot be generated due to an authentication failure
      Since:
      5.6
      See Also:
    • getPrincipal

      public Principal getPrincipal()
      Returns Principal whose credentials are used.
      Specified by:
      getPrincipal in interface AuthScheme
      Returns:
      user principal
      Since:
      5.6
      See Also:
    • buildClientFirst

      private String buildClientFirst()
    • buildClientFinalAndExpectV

      private String buildClientFinalAndExpectV() throws AuthenticationException
      Throws:
      AuthenticationException
    • zero

      private static void zero(byte[] a)
    • zeroAndClearExpectedV

      private void zeroAndClearExpectedV()
    • toParamMap

      private static Map<String,String> toParamMap(List<org.apache.hc.core5.http.NameValuePair> pairs)
    • parseAttrs

      private static Map<String,String> parseAttrs(String s) throws MalformedChallengeException
      Throws:
      MalformedChallengeException
    • genNonce

      private String genNonce()
    • escapeUser

      private static String escapeUser(String user)
    • quoteParam

      private static String quoteParam(String v)
    • hiPBKDF2

      private static byte[] hiPBKDF2(char[] password, byte[] salt, int iterations, int dkLen) throws GeneralSecurityException
      Throws:
      GeneralSecurityException
    • hmac

      private static byte[] hmac(byte[] key, String msg) throws GeneralSecurityException
      Throws:
      GeneralSecurityException
    • sha256

      private static byte[] sha256(byte[] in) throws GeneralSecurityException
      Throws:
      GeneralSecurityException
    • xor

      private static byte[] xor(byte[] a, byte[] b)
    • stringToB64

      private static String stringToB64(String s)
    • b64ToString

      private static String b64ToString(String b64) throws MalformedChallengeException
      Throws:
      MalformedChallengeException