summaryrefslogtreecommitdiffstats
path: root/src/lib-oauth2/oauth2.h
blob: 3d1d3ea6a1516e748483de68bacd0b4d87645bad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#ifndef OAUTH2_H
#define OAUTH2_H

#include "net.h"

struct dict;
struct oauth2_request;
struct oauth2_validation_key_cache;

struct oauth2_field {
	const char *name;
	const char *value;
};

ARRAY_DEFINE_TYPE(oauth2_field, struct oauth2_field);

struct oauth2_settings {
	struct http_client *client;
	/* GET tokeninfo from this URL, token is appended to URL
	   http://some.host/path?access_token= */
	const char *tokeninfo_url;
	/* POST grant password here, needs user credentials and client_*
	   settings */
	const char *grant_url;
	/* GET more information from this URL, uses Bearer authentication */
	const char *introspection_url;
	/* POST refresh here, needs refresh token and client_* settings */
	const char *refresh_url;
	/* client identificator for oauth2 server */
	const char *client_id;
	/* client secret for oauth2 server */
	const char *client_secret;
	/* access request scope for oauth2 server (optional) */
	const char *scope;
	/* key dict for looking up validation keys */
	struct dict *key_dict;
	/* cache for validation keys */
	struct oauth2_validation_key_cache *key_cache;
	/* valid issuer names */
	const char *const *issuers;

	enum {
		INTROSPECTION_MODE_GET_AUTH,
		INTROSPECTION_MODE_GET,
		INTROSPECTION_MODE_POST,
		INTROSPECTION_MODE_LOCAL,
	} introspection_mode;
	unsigned int timeout_msecs;
	/* Should X-Dovecot-Auth-* headers be sent */
	bool send_auth_headers;
	/* Should use grant password mechanism for authentication */
	bool use_grant_password;
};


struct oauth2_request_result {
	/* Oauth2 server response fields */
	ARRAY_TYPE(oauth2_field) *fields;
	/* Non-NULL if there was an unexpected internal error. */
	const char *error;
	/* timestamp token expires at */
	time_t expires_at;
	/* User authenticated successfully. Implies that error==NULL. */
	bool valid:1;
};

struct oauth2_request_input {
	const char *token;
	const char *service;
	struct ip_addr local_ip, real_local_ip, remote_ip, real_remote_ip;
	in_port_t local_port, real_local_port, remote_port, real_remote_port;
};

typedef void
oauth2_request_callback_t(struct oauth2_request_result*, void*);

bool oauth2_valid_token(const char *token);

struct oauth2_request*
oauth2_passwd_grant_start(const struct oauth2_settings *set,
			  const struct oauth2_request_input *input,
			  const char *username,
			  const char *password,
			  oauth2_request_callback_t *callback,
			  void *context);
#define oauth2_passwd_grant_start(set, input, username, password, callback, \
				  context) \
	oauth2_passwd_grant_start( \
		set, input - CALLBACK_TYPECHECK( \
			callback, void(*)(struct oauth2_request_result*, \
					  typeof(context))), \
		username, password, \
		(oauth2_request_callback_t*)callback, (void*)context);

struct oauth2_request*
oauth2_token_validation_start(const struct oauth2_settings *set,
			      const struct oauth2_request_input *input,
			      oauth2_request_callback_t *callback,
			      void *context);
#define oauth2_token_validation_start(set, input, callback, context) \
	oauth2_token_validation_start( \
		set, input - CALLBACK_TYPECHECK( \
			callback, void(*)(struct oauth2_request_result*, \
					  typeof(context))), \
		(oauth2_request_callback_t*)callback, (void*)context);

struct oauth2_request*
oauth2_introspection_start(const struct oauth2_settings *set,
			   const struct oauth2_request_input *input,
			   oauth2_request_callback_t *callback,
			   void *context);
#define oauth2_introspection_start(set, input, callback, context) \
	oauth2_introspection_start( \
		set, input - CALLBACK_TYPECHECK( \
			callback, void(*)(struct oauth2_request_result*, \
					  typeof(context))), \
		(oauth2_request_callback_t*)callback, (void*)context);

struct oauth2_request *
oauth2_refresh_start(const struct oauth2_settings *set,
		     const struct oauth2_request_input *input,
		     oauth2_request_callback_t *callback,
		     void *context);
#define oauth2_refresh_start(set, input, callback, context) \
	oauth2_refresh_start( \
		set, input - CALLBACK_TYPECHECK( \
			callback, void(*)(struct oauth2_request_result*, \
					  typeof(context))), \
		(oauth2_request_callback_t*)callback, (void*)context);

/* Abort without calling callback, use this to cancel the request */
void oauth2_request_abort(struct oauth2_request **);

int oauth2_try_parse_jwt(const struct oauth2_settings *set,
			 const char *token, ARRAY_TYPE(oauth2_field) *fields,
			 bool *is_jwt_r, const char **error_r);

/* Initialize validation key cache */
struct oauth2_validation_key_cache *oauth2_validation_key_cache_init(void);

/* Evict given key ID from cache, returns 0 on successful eviction */
int oauth2_validation_key_cache_evict(struct oauth2_validation_key_cache *cache,
				      const char *key_id);

/* Deinitialize validation key cache */
void oauth2_validation_key_cache_deinit(
	struct oauth2_validation_key_cache **_cache);

#endif