Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set the Bearer prefix in bindings. #5484

Merged
merged 5 commits into from Apr 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/damlc/tests/src/DA/Test/Repl.hs
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
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
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
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
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
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)
}
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
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)
}
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
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)
}