1 /*
2  *
3  * Copyright 2016 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_OAUTH2_CREDENTIALS_H
20 #define GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_OAUTH2_CREDENTIALS_H
21 
22 #include <grpc/support/port_platform.h>
23 
24 #include <string>
25 
26 #include <grpc/grpc_security.h>
27 #include "src/core/lib/json/json.h"
28 #include "src/core/lib/security/credentials/credentials.h"
29 #include "src/core/lib/uri/uri_parser.h"
30 
31 // Constants.
32 #define GRPC_STS_POST_MINIMAL_BODY_FORMAT_STRING                               \
33   "grant_type=urn:ietf:params:oauth:grant-type:token-exchange&subject_token=%" \
34   "s&subject_token_type=%s"
35 
36 // auth_refresh_token parsing.
37 struct grpc_auth_refresh_token {
38   const char* type;
39   char* client_id;
40   char* client_secret;
41   char* refresh_token;
42 };
43 /// Returns 1 if the object is valid, 0 otherwise.
44 int grpc_auth_refresh_token_is_valid(
45     const grpc_auth_refresh_token* refresh_token);
46 
47 /// Creates a refresh token object from string. Returns an invalid object if a
48 /// parsing error has been encountered.
49 grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
50     const char* json_string);
51 
52 /// Creates a refresh token object from parsed json. Returns an invalid object
53 /// if a parsing error has been encountered.
54 grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json(
55     const grpc_core::Json& json);
56 
57 /// Destructs the object.
58 void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token* refresh_token);
59 
60 // -- Oauth2 Token Fetcher credentials --
61 //
62 //  This object is a base for credentials that need to acquire an oauth2 token
63 //  from an http service.
64 
65 struct grpc_oauth2_pending_get_request_metadata {
66   grpc_credentials_mdelem_array* md_array;
67   grpc_closure* on_request_metadata;
68   grpc_polling_entity* pollent;
69   struct grpc_oauth2_pending_get_request_metadata* next;
70 };
71 
72 class grpc_oauth2_token_fetcher_credentials : public grpc_call_credentials {
73  public:
74   grpc_oauth2_token_fetcher_credentials();
75   ~grpc_oauth2_token_fetcher_credentials() override;
76 
77   bool get_request_metadata(grpc_polling_entity* pollent,
78                             grpc_auth_metadata_context context,
79                             grpc_credentials_mdelem_array* md_array,
80                             grpc_closure* on_request_metadata,
81                             grpc_error** error) override;
82 
83   void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array,
84                                    grpc_error* error) override;
85 
86   void on_http_response(grpc_credentials_metadata_request* r,
87                         grpc_error* error);
88   std::string debug_string() override;
89 
90  protected:
91   virtual void fetch_oauth2(grpc_credentials_metadata_request* req,
92                             grpc_httpcli_context* httpcli_context,
93                             grpc_polling_entity* pollent, grpc_iomgr_cb_func cb,
94                             grpc_millis deadline) = 0;
95 
96  private:
97   gpr_mu mu_;
98   grpc_mdelem access_token_md_ = GRPC_MDNULL;
99   gpr_timespec token_expiration_;
100   bool token_fetch_pending_ = false;
101   grpc_oauth2_pending_get_request_metadata* pending_requests_ = nullptr;
102   grpc_httpcli_context httpcli_context_;
103   grpc_polling_entity pollent_;
104 };
105 
106 // Google refresh token credentials.
107 class grpc_google_refresh_token_credentials final
108     : public grpc_oauth2_token_fetcher_credentials {
109  public:
110   grpc_google_refresh_token_credentials(grpc_auth_refresh_token refresh_token);
111   ~grpc_google_refresh_token_credentials() override;
112 
refresh_token()113   const grpc_auth_refresh_token& refresh_token() const {
114     return refresh_token_;
115   }
116 
117   std::string debug_string() override;
118 
119  protected:
120   void fetch_oauth2(grpc_credentials_metadata_request* req,
121                     grpc_httpcli_context* httpcli_context,
122                     grpc_polling_entity* pollent, grpc_iomgr_cb_func cb,
123                     grpc_millis deadline) override;
124 
125  private:
126   grpc_auth_refresh_token refresh_token_;
127   grpc_closure http_post_cb_closure_;
128 };
129 
130 // Access token credentials.
131 class grpc_access_token_credentials final : public grpc_call_credentials {
132  public:
133   grpc_access_token_credentials(const char* access_token);
134   ~grpc_access_token_credentials() override;
135 
136   bool get_request_metadata(grpc_polling_entity* pollent,
137                             grpc_auth_metadata_context context,
138                             grpc_credentials_mdelem_array* md_array,
139                             grpc_closure* on_request_metadata,
140                             grpc_error** error) override;
141 
142   void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array,
143                                    grpc_error* error) override;
144 
145   std::string debug_string() override;
146 
147  private:
148   grpc_mdelem access_token_md_;
149 };
150 
151 // Private constructor for refresh token credentials from an already parsed
152 // refresh token. Takes ownership of the refresh token.
153 grpc_core::RefCountedPtr<grpc_call_credentials>
154 grpc_refresh_token_credentials_create_from_auth_refresh_token(
155     grpc_auth_refresh_token token);
156 
157 // Exposed for testing only.
158 grpc_credentials_status
159 grpc_oauth2_token_fetcher_credentials_parse_server_response(
160     const struct grpc_http_response* response, grpc_mdelem* token_md,
161     grpc_millis* token_lifetime);
162 
163 namespace grpc_core {
164 // Exposed for testing only. This function validates the options, ensuring that
165 // the required fields are set, and outputs the parsed URL of the STS token
166 // exchanged service.
167 grpc_error* ValidateStsCredentialsOptions(
168     const grpc_sts_credentials_options* options, grpc_uri** sts_url);
169 }  // namespace grpc_core
170 
171 #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_OAUTH2_CREDENTIALS_H */
172