Skip to content

Commit

Permalink
Set the Bearer prefix in bindings. (digital-asset#5484)
Browse files Browse the repository at this point in the history
* Set the `Bearer ` prefix in bindings.
* Make the `Bearer ` prefix in the authorization header mandatory.
* Bearer prefix can be removed from the token file.

CHANGELOG_BEGIN
[Extractor]: The ``Bearer `` prefix can be removed from the token file.
It is added automatically.
[Navigator]: The ``Bearer `` prefix can be removed from the token file.
It is added automatically.
[DAML Script] The ``Bearer `` prefix can be removed from the token file. It
is added automatically.
[DAML Repl] The ``Bearer `` prefix can be removed from the token file. It is
added automatically.
[Scala Bindings] The ``Bearer `` prefix can be removed from the token. It is
added automatically.
[Java Bindings] The ``Bearer `` prefix can be removed from the token. It is
added automatically.
[DAML Integration Kit] ``AuthService`` implementations MUST read the
``Authorization`` header and the value of the header MUST start with
``Bearer ``.
CHANGELOG_END
  • Loading branch information
gerolf-da authored Apr 8, 2020
1 parent 8261af8 commit 9743374
Show file tree
Hide file tree
Showing 10 changed files with 29 additions and 20 deletions.
2 changes: 1 addition & 1 deletion compiler/damlc/tests/src/DA/Test/Repl.hs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ withTokenFile f = withResource acquire release (f . fmap fst)
where
acquire = mask_ $ do
(file, delete) <- newTempFile
writeFile file ("Bearer " <> jwtToken)
writeFile file jwtToken
pure (file, delete)
release = snd

Expand Down
2 changes: 1 addition & 1 deletion daml-script/test/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ genrule(
outs = ["test-auth-token.jwt"],
cmd = """
cat <<EOF > $(location test-auth-token.jwt)
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwczovL2RhbWwuY29tL2xlZGdlci1hcGkiOnsiYWRtaW4iOmZhbHNlLCJhY3RBcyI6WyJBbGljZSIsIkJvYiJdfX0.UYogXMZvmhzzjmsmKayaDsI2hGKh1T2Sz5l9h4tdgGM
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwczovL2RhbWwuY29tL2xlZGdlci1hcGkiOnsiYWRtaW4iOmZhbHNlLCJhY3RBcyI6WyJBbGljZSIsIkJvYiJdfX0.UYogXMZvmhzzjmsmKayaDsI2hGKh1T2Sz5l9h4tdgGM
EOF
""",
)
Expand Down
5 changes: 2 additions & 3 deletions docs/source/daml-script/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,8 @@ To run DAML script against the JSON API you have to pass the ``--json-api`` para
ledger API command, e.g., one ``createCmd`` or one ``exerciseCmd``.
#. The JSON API requires an authentication token even when it is run
against an unauthenticated ledger. The authentication token must be
a JWT ``Bearer`` token so the ``--access-token-file`` passed to
``daml script`` should only contain the actual JWT without the
``Bearer`` prefix.
a JWT token so the ``--access-token-file`` passed to
``daml script`` should contain the actual JWT token.
#. The token must contain exactly one party in ``actAs`` and/or
``readAs``. This party will be used for ``submit`` and
``query``. Passing a party as the argument to ``submit`` and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ object LedgerClientJwt {
type AllocateParty =
(Jwt, Option[Ref.Party], Option[String]) => Future[api.domain.PartyDetails]

private def bearer(jwt: Jwt): Some[String] = Some(s"Bearer ${jwt.value: String}")
private def bearer(jwt: Jwt): Some[String] = Some(jwt.value: String)

def submitAndWaitForTransaction(client: LedgerClient): SubmitAndWaitForTransaction =
(jwt, req) => client.commandServiceClient.submitAndWaitForTransaction(req, bearer(jwt))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public LedgerCallCredentials(String token) {
@Override
public void applyRequestMetadata(RequestInfo requestInfo, Executor appExecutor, MetadataApplier applier) {
Metadata metadata = new Metadata();
metadata.put(LedgerCallCredentials.header, token);
metadata.put(LedgerCallCredentials.header, token.startsWith("Bearer ") ? token : "Bearer " + token);
applier.apply(metadata);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,23 @@ package com.daml.ledger.api.auth

import java.util.concurrent.CompletionStage

import io.grpc.Metadata

/** An interface for authorizing the ledger API access to a participant.
*
* The AuthService is responsible for converting request metadata (such as
* the HTTP headers) into a set of [[Claims]].
* These claims are then used by the ledger API server to check whether the
* request is authorized.
*
* - The authorization information MUST be specified in the `Authorization` header.
* - The value of the `Authorization` header MUST start with `Bearer `
* (notice the trailing space of the prefix).
* - An [[AuthService]] implementation MAY use other headers when converting metadata
* to claims.
*
*
*
* For example, a participant could:
* - Ask all ledger API users to attach an `Authorization` header
* with a JWT token as the header value.
Expand All @@ -27,4 +37,11 @@ trait AuthService {
* Return a failed future to reject requests with an INTERNAL error status.
*/
def decodeMetadata(headers: io.grpc.Metadata): CompletionStage[Claims]

/**
* The [[Metadata.Key]] to use for looking up the `Authorization` header in the
* request metadata.
*/
val AUTHORIZATION_KEY: Metadata.Key[String] =
Metadata.Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER)
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class AuthServiceJWT(verifier: JwtVerifierBase) extends AuthService {

for {
headerValue <- Option
.apply(headers.get(AuthServiceJWT.AUTHORIZATION_KEY))
.apply(headers.get(AUTHORIZATION_KEY))
.toRight(Error("Authorization header not found"))
token <- bearerTokenRegex
.findFirstMatchIn(headerValue)
Expand Down Expand Up @@ -85,9 +85,6 @@ class AuthServiceJWT(verifier: JwtVerifierBase) extends AuthService {
object AuthServiceJWT {
final case class Error(message: String)

val AUTHORIZATION_KEY: Metadata.Key[String] =
Metadata.Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER)

def apply(verifier: com.auth0.jwt.interfaces.JWTVerifier) =
new AuthServiceJWT(new JwtVerifier(verifier))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import io.grpc.Metadata
*/
final class AuthServiceStatic(claims: PartialFunction[String, Claims]) extends AuthService {
override def decodeMetadata(headers: Metadata): CompletionStage[Claims] = {
if (headers.containsKey(AuthServiceStatic.AUTHORIZATION_KEY)) {
val authorizationValue = headers.get(AuthServiceStatic.AUTHORIZATION_KEY)
if (headers.containsKey(AUTHORIZATION_KEY)) {
val authorizationValue = headers.get(AUTHORIZATION_KEY).stripPrefix("Bearer ")
CompletableFuture.completedFuture(claims.lift(authorizationValue).getOrElse(Claims.empty))
} else {
CompletableFuture.completedFuture(Claims.empty)
Expand All @@ -24,8 +24,5 @@ final class AuthServiceStatic(claims: PartialFunction[String, Claims]) extends A
}

object AuthServiceStatic {
private val AUTHORIZATION_KEY: Metadata.Key[String] =
Metadata.Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER)

def apply(claims: PartialFunction[String, Claims]) = new AuthServiceStatic(claims)
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ object Main {

Files.write(
changeExtension(outputFile, "-bearer.txt").toPath,
s"Bearer ${signed.value}".getBytes(StandardCharsets.UTF_8))
signed.value.getBytes(StandardCharsets.UTF_8))

Files.write(
changeExtension(outputFile, "-payload.json").toPath,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ trait SandboxFixtureWithAuth extends SandboxFixture { self: Suite =>
.getOrElse(sys.error("Failed to generate token"))
.value

def toHeader(payload: AuthServiceJWTPayload, secret: String = jwtSecret) =
s"Bearer ${signed(payload, secret)}"

def toHeader(payload: AuthServiceJWTPayload, secret: String = jwtSecret): String =
signed(payload, secret)
}

0 comments on commit 9743374

Please sign in to comment.