-
Notifications
You must be signed in to change notification settings - Fork 53
/
oauth2.cfc
192 lines (182 loc) · 7.3 KB
/
oauth2.cfc
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/**
* @displayname oauth2
* @output false
* @hint The oauth2 object.
* @author Matt Gifford
* @website https://www.monkehworks.com
* @purpose A ColdFusion Component to manage authentication using the OAuth2 protocol.
**/
component accessors="true"{
property name="client_id" type="string";
property name="client_secret" type="string";
property name="authEndpoint" type="string";
property name="accessTokenEndpoint" type="string";
property name="redirect_uri" type="string";
property name="PKCE" type="struct";
/**
* I return an initialized oauth2 object instance.
* @client_id The client ID for your application.
* @client_secret The client secret for your application.
* @authEndpoint The URL endpoint that handles the authorisation.
* @accessTokenEndpoint The URL endpoint that handles retrieving the access token.
* @redirect_uri The URL to redirect the user back to following authentication.
**/
public oauth2 function init(
required string client_id,
required string client_secret,
required string authEndpoint,
required string accessTokenEndpoint,
required string redirect_uri
){
setClient_id( arguments.client_id );
setClient_secret( arguments.client_secret );
setAuthEndpoint( arguments.authEndpoint );
setAccessTokenEndpoint( arguments.accessTokenEndpoint );
setRedirect_uri( arguments.redirect_uri );
return this;
}
/**
* I return the URL as a string which we use to redirect the user for authentication. |
* The method will handle the client_id and redirect_uri values for you. Anything else you need to send to the provider in the URL can be sent via the parameters argument.
* @parameters A structure containing key / value pairs of data to be included in the URL string.
**/
public string function buildRedirectToAuthURL( struct parameters={} ) {
var objAuthBuilder = new utils.authStringBuilder(
authEndpoint = getAuthEndpoint(),
client_id = getClient_id(),
redirect_uri = getRedirect_uri()
);
return objAuthBuilder.withParams( arguments.parameters ).get();
}
/**
* I return an instance of the authStringBuilder class. The actual link string is generated by then calling the .get() method on the class object.
* The method will handle the client_id and redirect_uri values for you. Anything else you need to send to the provider in the URL can be sent via the parameters argument.
* @parameters A structure containing key / value pairs of data to be included in the URL string.
**/
public authStringBuilder function buildRedirectToAuthURLWithBuilder( struct parameters={} ) {
var objAuthBuilder = new utils.authStringBuilder(
authEndpoint = getAuthEndpoint(),
client_id = getClient_id(),
redirect_uri = getRedirect_uri()
);
return objAuthBuilder.withParams( arguments.parameters );
}
/**
* I make the HTTP request to obtain the access token.
* @code The code returned from the authentication request.
* @formfields An optional array of structs for the provider requirements to add new form fields.
* @headers An optional array of structs to add custom headers to the request if required.
**/
public struct function makeAccessTokenRequest(
required string code,
array formfields = [],
array headers = []
){
var stuResponse = {};
var httpService = new http();
httpService.setMethod( "post" );
httpService.setCharset( "utf-8" );
httpService.setUrl( getAccessTokenEndpoint() );
if( arrayLen( arguments.headers ) ){
for( var item in arguments.headers ){
httpService.addParam( type="header", name=item[ 'name' ], value=item[ 'value' ] );
}
}
httpService.addParam( type="formfield", name="client_id", value=getClient_id() );
httpService.addParam( type="formfield", name="client_secret", value=getClient_secret() );
httpService.addParam( type="formfield", name="code", value=arguments.code );
httpService.addParam( type="formfield", name="redirect_uri", value=getRedirect_uri() );
httpService.addParam( type="formfield", name="grant_type", value='authorization_code' );
if( arrayLen( arguments.formfields ) ){
for( var item in arguments.formfields ){
httpService.addParam( type="formfield", name=item[ 'name' ], value=item[ 'value' ] );
}
}
var result = httpService.send().getPrefix();
if( '200' == result.ResponseHeader[ 'Status_Code' ] ) {
stuResponse.success = true;
stuResponse.content = result.FileContent;
} else {
stuResponse.success = false;
stuResponse.content = result.Statuscode;
}
return stuResponse;
}
/**
* I make the HTTP request to refresh the access token.
* @refresh_token The refresh_token returned from the accessTokenRequest request.
**/
public struct function refreshAccessTokenRequest(
required string refresh_token,
array formfields = [],
array headers = []
){
var stuResponse = {};
var httpService = new http();
httpService.setMethod( "post" );
httpService.setCharset( "utf-8" );
httpService.setUrl( getAccessTokenEndpoint() );
httpService.addParam( type="header", name="Content-Type", value="application/x-www-form-urlencoded" );
if( arrayLen( arguments.headers ) ){
for( var item in arguments.headers ){
httpService.addParam( type="header", name=item[ 'name' ], value=item[ 'value' ] );
}
}
httpService.addParam( type="formfield", name="client_id", value=getClient_id() );
httpService.addParam( type="formfield", name="client_secret", value=getClient_secret() );
httpService.addParam( type="formfield", name="refresh_token", value=arguments.refresh_token );
httpService.addParam( type="formfield", name="grant_type", value="refresh_token" );
if( arrayLen( arguments.formfields ) ){
for( var item in arguments.formfields ){
httpService.addParam( type="formfield", name=item[ 'name' ], value=item[ 'value' ] );
}
}
var result = httpService.send().getPrefix();
if( '200' == result.ResponseHeader[ 'Status_Code' ] ) {
stuResponse.success = true;
stuResponse.content = result.FileContent;
} else {
stuResponse.success = false;
stuResponse.content = result.Statuscode;
}
return stuResponse;
}
/**
* I return a string containing any extra URL parameters to concatenate and pass through when authenticating.
* @argScope A structure containing key / value pairs of data to be included in the URL string.
**/
public string function buildParamString( struct argScope={} ) {
var strURLParam = '?';
if( structCount( arguments.argScope ) ) {
var intCount = 1;
for( var key in arguments.argScope ) {
if( listLen( strURLParam ) && intCount > 1 ) {
strURLParam = strURLParam & '&';
}
strURLParam = strURLParam & lcase( key ) & '=' & trim( arguments.argScope[ key ] );
intCount++;
}
}
return strURLParam;
}
/**
* Returns the properties as a struct
*/
public struct function getMemento(){
var result = {};
for( var thisProp in getMetaData( this ).properties ){
if( structKeyExists( variables, thisProp[ 'name' ] ) ){
result[ thisProp[ 'name' ] ] = variables[ thisProp[ 'name' ] ];
}
}
return result;
}
/**
* Generates a struct containing the code verifier and code challenge
* values for use with the PKCE extension.
*/
public struct function generatePKCE(){
var objPKCE = new utils.deps.pkce.pkce();
return objPKCE.generatePKCE();
}
}