xref: /aosp_15_r20/external/tink/cc/examples/jwt/jwt_sign.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16 // [START jwt-sign]
17 // An example for signing JSON Web Tokens (JWT).
18 #include <iostream>
19 #include <memory>
20 #include <ostream>
21 #include <string>
22 #include <utility>
23 
24 #include "absl/flags/flag.h"
25 #include "absl/flags/parse.h"
26 #include "absl/log/check.h"
27 #include "util/util.h"
28 #include "tink/jwt/jwt_public_key_sign.h"
29 #include "tink/jwt/jwt_signature_config.h"
30 #include "tink/jwt/raw_jwt.h"
31 #include "tink/keyset_handle.h"
32 #include "tink/util/status.h"
33 
34 ABSL_FLAG(std::string, keyset_filename, "", "Keyset file in JSON format");
35 ABSL_FLAG(std::string, audience, "", "Expected audience in the token");
36 ABSL_FLAG(std::string, token_filename, "", "Path to the token file");
37 
38 namespace {
39 
40 using ::crypto::tink::JwtPublicKeySign;
41 using ::crypto::tink::KeysetHandle;
42 using ::crypto::tink::RawJwt;
43 using ::crypto::tink::RawJwtBuilder;
44 using ::crypto::tink::util::Status;
45 using ::crypto::tink::util::StatusOr;
46 
ValidateParams()47 void ValidateParams() {
48   // [START_EXCLUDE]
49   CHECK(!absl::GetFlag(FLAGS_keyset_filename).empty())
50       << "Keyset file must be specified";
51   CHECK(!absl::GetFlag(FLAGS_audience).empty())
52       << "Expected audience in the token must be specified";
53   CHECK(!absl::GetFlag(FLAGS_token_filename).empty())
54       << "Token file must be specified";
55   // [END_EXCLUDE]
56 }
57 
58 }  // namespace
59 
60 namespace tink_cc_examples {
61 
62 // JWT sign example CLI implementation.
JwtSign(const std::string & keyset_filename,absl::string_view audience,const std::string & token_filename)63 Status JwtSign(const std::string& keyset_filename, absl::string_view audience,
64                const std::string& token_filename) {
65   Status result = crypto::tink::JwtSignatureRegister();
66   if (!result.ok()) return result;
67 
68   // Read the keyset from file.
69   StatusOr<std::unique_ptr<KeysetHandle>> keyset_handle =
70       ReadJsonCleartextKeyset(keyset_filename);
71   if (!keyset_handle.ok()) return keyset_handle.status();
72   StatusOr<RawJwt> raw_jwt =
73       RawJwtBuilder()
74           .AddAudience(audience)
75           .SetExpiration(absl::Now() + absl::Seconds(100))
76           .Build();
77   if (!raw_jwt.ok()) return raw_jwt.status();
78   StatusOr<std::unique_ptr<JwtPublicKeySign>> jwt_signer =
79       (*keyset_handle)->GetPrimitive<JwtPublicKeySign>();
80   if (!jwt_signer.ok()) return jwt_signer.status();
81 
82   StatusOr<std::string> token = (*jwt_signer)->SignAndEncode(*raw_jwt);
83   if (!token.ok()) return token.status();
84 
85   return WriteToFile(*token, token_filename);
86 }
87 
88 }  // namespace tink_cc_examples
89 
main(int argc,char ** argv)90 int main(int argc, char** argv) {
91   absl::ParseCommandLine(argc, argv);
92 
93   ValidateParams();
94 
95   std::string keyset_filename = absl::GetFlag(FLAGS_keyset_filename);
96   std::string audience = absl::GetFlag(FLAGS_audience);
97   std::string token_filename = absl::GetFlag(FLAGS_token_filename);
98 
99   std::clog << "Using keyset in " << keyset_filename << " to ";
100   std::clog << " generate and sign a token using audience '" << audience
101             << "'; the resulting signature is written to " << token_filename
102             << std::endl;
103 
104   CHECK_OK(
105       tink_cc_examples::JwtSign(keyset_filename, audience, token_filename));
106   return 0;
107 }
108 // [END jwt-sign]
109