1
1
package com .example .fn ;
2
2
3
- import java .net .http .HttpClient ;
4
- import java .net .http .HttpRequest ;
3
+ import static com .example .fn .util .ResourceServerConfig .TOKEN_PREFIX ;
4
+ import static com .example .fn .util .ResourceServerConfig .CONFIG_KEY_IDCS_URL ;
5
+ import static com .example .fn .util .ResourceServerConfig .CONFIG_KEY_CLIENT_ID ;
6
+ import static com .example .fn .util .ResourceServerConfig .CONFIG_KEY_CLIENT_SECRET ;
7
+ import static com .example .fn .util .ResourceServerConfig .CONFIG_KEY_SCOPE_AUD ;
8
+ import static com .example .fn .util .ResourceServerConfig .DEFAULT_GRANT_TYPE ;
9
+ import static com .example .fn .util .ResourceServerConfig .TOKEN_CLAIM_KEY_EXPIRY ;
10
+ import static com .example .fn .util .ResourceServerConfig .TOKEN_CLAIM_KEY_SUBJECT ;
11
+ import static com .example .fn .util .ResourceServerConfig .TOKEN_CLAIM_KEY_SCOPE ;
12
+
5
13
import java .net .http .HttpResponse ;
6
- import java .net .URI ;
7
14
8
15
import java .io .IOException ;
9
16
import java .io .UnsupportedEncodingException ;
10
17
import java .lang .InterruptedException ;
11
18
import org .json .JSONObject ;
12
- import java .util .*;
13
19
14
- public class BasicAuth {
15
- public static class Input {
16
- public String type ;
17
- public String token ;
18
- }
20
+ import com .example .fn .util .Helper ;
21
+ import com .fnproject .fn .api .FnConfiguration ;
22
+ import com .fnproject .fn .api .RuntimeContext ;
19
23
20
- public static class Result {
21
- public boolean active = false ;
22
- public String principal ;
23
- public String [] scope ;
24
- public String expiresAt ;
25
- }
24
+ import java .util .*;
26
25
27
- private static final String TOKEN_PREFIX = "Basic " ;
28
- private static final String IDCS_URL = ResourceServerConfig .IDCS_URL ;
26
+ /**
27
+ * Main class implementing the {@code handleRequest} method, takes the user
28
+ * credentials as input, authenticates the credentials against the identity
29
+ * provider and if the authentication is successful then returns the following
30
+ * claims from the access token <br/>
31
+ * <ul>
32
+ * <li>exp</li>
33
+ * <li>sub</li>
34
+ * <li>scope</li>
35
+ * </ul>
36
+ */
37
+ public class BasicAuth {
29
38
30
- public String [] getUserDetailsFromToken (String token ) {
31
- String data = token .substring (TOKEN_PREFIX .length ());
32
- String [] user = new String (Base64 .getDecoder ().decode (data )).split (":" , 2 );
33
- return user ;
39
+ private static String IDCS_URL = null ;
40
+ private static String CLIENT_ID = null ;
41
+ private static String CLIENT_SECRET = null ;
42
+ private static String SCOPE_AUD = null ;
43
+
44
+ /**
45
+ * Reads the configuration parameters and sets the respective variables during
46
+ * function initialization.
47
+ *
48
+ * @param {@link RuntimeContext} ctx
49
+ */
50
+ @ FnConfiguration
51
+ public void config (final RuntimeContext ctx ) {
52
+ IDCS_URL = ctx .getConfigurationByKey (CONFIG_KEY_IDCS_URL ).orElse (null );
53
+ CLIENT_ID = ctx .getConfigurationByKey (CONFIG_KEY_CLIENT_ID ).orElse (null );
54
+ CLIENT_SECRET = ctx .getConfigurationByKey (CONFIG_KEY_CLIENT_SECRET ).orElse (null );
55
+ SCOPE_AUD = ctx .getConfigurationByKey (CONFIG_KEY_SCOPE_AUD ).orElse (null );
34
56
}
35
57
36
- public Result handleRequest (Input input ) throws UnsupportedEncodingException , InterruptedException {
37
- Result returnValue = new Result ();
58
+ /**
59
+ * Entry point of the function
60
+ *
61
+ * @param {@link Input} input
62
+ * @return {@link Result}
63
+ * @throws UnsupportedEncodingException
64
+ * @throws InterruptedException
65
+ */
66
+ public Result handleRequest (final Input input ) throws UnsupportedEncodingException , InterruptedException {
67
+ final Result returnValue = new Result ();
68
+
69
+ if (!isConfigValid ()) {
70
+ returnValue .active = false ;
71
+ System .out .println (
72
+ "Function initialization error, all config parameters not set, please ensure that following config variables are set IDCS_URL, CLIENT_ID, CLIENT_SECRET" );
73
+ return returnValue ;
74
+ }
38
75
39
76
if (input .token == null || !input .token .startsWith (TOKEN_PREFIX )) {
40
77
returnValue .active = false ;
41
78
System .out .println ("Request error, missing credentials" );
42
79
return returnValue ;
43
80
}
44
81
45
- String [] user = getUserDetailsFromToken (input .token );
82
+ final String [] user = getUserDetailsFromToken (input .token );
46
83
if (user .length != 2 || user [0 ] == null || user [0 ].isEmpty () || user [1 ] == null || user [1 ].isEmpty ()) {
84
+ returnValue .active = false ;
47
85
System .out .println ("Request error username or password missing" );
48
86
return returnValue ;
49
87
}
50
88
51
- String username = user [0 ];
52
- String password = user [1 ];
53
- String clientId = ResourceServerConfig .CLIENT_ID ;
54
- String clientSecret = ResourceServerConfig .CLIENT_SECRET ;
55
- String authzHdrVal = clientId + ":" + clientSecret ;
56
- String idcsScope = ResourceServerConfig .SCOPE_AUD ;
57
-
58
- String reqBody = "grant_type=password" +
59
- "&username=" + username +
60
- "&password=" + password +
61
- "&scope=" + idcsScope ;
89
+ final String authzHdrVal = CLIENT_ID + ":" + CLIENT_SECRET ;
90
+ final String reqBody = Helper .createRequestBody (user [0 ], user [1 ], SCOPE_AUD , DEFAULT_GRANT_TYPE );
62
91
63
92
try {
64
- HttpClient client = HttpClient .newHttpClient ();
65
-
66
- HttpRequest request = HttpRequest .newBuilder ()
67
- .uri (URI .create (IDCS_URL ))
68
- .header ("Content-Type" , "application/x-www-form-urlencoded" )
69
- .header ("Authorization" , "Basic " + Base64 .getEncoder ().encodeToString (authzHdrVal .getBytes ("UTF-8" )))
70
- .POST (HttpRequest .BodyPublishers .ofString (reqBody ))
71
- .build ();
72
-
73
- HttpResponse <String > response = client .send ( request ,
74
- HttpResponse .BodyHandlers .ofString () );
75
-
93
+ final HttpResponse <String > response = Helper .callIDCS (IDCS_URL , authzHdrVal , reqBody );
76
94
77
95
if (response .statusCode () == 200 ) {
96
+ final String responseString = (String ) response .body ();
97
+ final JSONObject payload = Helper .getTokenBody (responseString );
78
98
79
- String responseString = (String ) response .body ();
80
- String [] chunks = responseString .split ("\\ ." );
81
- String respjson = new String (Base64 .getUrlDecoder ().decode (chunks [1 ]));
82
- JSONObject payload = new JSONObject (respjson );
83
- Date expTime = new Date (payload .getLong ("exp" )*1000 );
84
-
85
- returnValue .principal = payload .getString ("sub" );
86
- returnValue .scope = payload .getString ("scope" ).split (" " );
99
+ final Date expTime = new Date (payload .getLong (TOKEN_CLAIM_KEY_EXPIRY ) * 1000 );
100
+ returnValue .principal = payload .getString (TOKEN_CLAIM_KEY_SUBJECT );
101
+ returnValue .scope = payload .getString (TOKEN_CLAIM_KEY_SCOPE ).split (" " );
87
102
returnValue .expiresAt = expTime .toString ();
88
103
returnValue .active = true ;
104
+
89
105
System .out .println ("Authentication successful" );
90
106
}
91
107
} catch (IOException e ) {
92
108
e .printStackTrace ();
93
109
}
94
110
return returnValue ;
95
111
}
112
+
113
+ /**
114
+ * Returns true if all the configuration variables are set else returns false
115
+ *
116
+ * @return
117
+ */
118
+ private boolean isConfigValid () {
119
+ if (IDCS_URL != null && !IDCS_URL .trim ().isEmpty ()
120
+ && CLIENT_ID != null && !CLIENT_ID .trim ().isEmpty ()
121
+ && CLIENT_SECRET != null && !CLIENT_SECRET .isEmpty ()
122
+ && SCOPE_AUD != null && !SCOPE_AUD .trim ().isEmpty ()) {
123
+ return true ;
124
+ }
125
+ return false ;
126
+ }
127
+
128
+ /**
129
+ * The input contains the username and password in {@link Base64} encoded
130
+ * format. The format of the token is Base64 encoded <username>:<password>. This
131
+ * function decodes the token and returns the username and password.
132
+ *
133
+ * @param {@link String} token
134
+ * @return {@link String} array with username and password
135
+ */
136
+ private String [] getUserDetailsFromToken (final String token ) {
137
+ final String data = token .substring (TOKEN_PREFIX .length ());
138
+ final String [] user = new String (Base64 .getDecoder ().decode (data )).split (":" , 2 );
139
+ return user ;
140
+ }
141
+
142
+ public static class Input {
143
+ public String type ;
144
+ public String token ;
145
+ }
146
+
147
+ public static class Result {
148
+ public boolean active = false ;
149
+ public String principal ;
150
+ public String [] scope ;
151
+ public String expiresAt ;
152
+ }
96
153
}
0 commit comments