@@ -78,6 +78,69 @@ public final class BasicAuthResource extends OpenDcsResource
7878 @ Context
7979 private HttpHeaders httpHeaders ;
8080
81+ @ POST
82+ @ Path ("credentials" )
83+ @ Consumes (MediaType .APPLICATION_JSON )
84+ @ Produces (MediaType .APPLICATION_JSON )
85+ @ RolesAllowed ({ApiConstants .ODCS_API_GUEST })
86+ @ Operation (
87+ summary = "The ‘credentials’ POST method is used to obtain a new token" ,
88+ description = "The user name and password provided must be a valid login for the underlying database. \n "
89+ + "Also, that user must be assigned either of the roles OTSDB_ADMIN or OTSDB_MGR.\n "
90+ + "--- \n \n \n "
91+ + "Starting in **API Version 0.0.3**, authentication credentials (username and password) "
92+ + "may be passed as shown above in the POST body. \n "
93+ + "They may also be passed in a GET call to the 'credentials' method, "
94+ + "(e.g. '*http://localhost:8080/odcsapi/credentials*') containing an HTTP Authentication Basic "
95+ + "header in the form 'username:password'. \n \n The returned data to the GET call will be empty." ,
96+ requestBody = @ RequestBody (
97+ description = "Login Credentials" ,
98+ required = true ,
99+ content = @ Content (
100+ mediaType = MediaType .APPLICATION_JSON ,
101+ schema = @ Schema (implementation = Credentials .class )
102+ )
103+ ),
104+ responses = {
105+ @ ApiResponse (
106+ responseCode = "200" ,
107+ description = "Successful authentication."
108+ ),
109+ @ ApiResponse (
110+ responseCode = "400" ,
111+ description = "Bad request - null or otherwise invalid credentials." ,
112+ content = @ Content (mediaType = MediaType .APPLICATION_JSON ,
113+ schema = @ Schema (type = "object" , implementation = StringToClassMapItem .class ),
114+ examples = @ ExampleObject (value = "{\" status\" :400," +
115+ "\" message\" : \" Neither username nor password may be null.\" }" ))
116+ ),
117+ @ ApiResponse (
118+ responseCode = "403" ,
119+ description = "Invalid credentials or insufficient role." ,
120+ content = @ Content (mediaType = MediaType .APPLICATION_JSON ,
121+ schema = @ Schema (type = "object" , implementation = StringToClassMapItem .class ),
122+ examples = @ ExampleObject (value = "{\" status\" :403," +
123+ "\" message\" :\" Failed to authorize user.\" }" ))
124+ ),
125+ @ ApiResponse (
126+ responseCode = "500" ,
127+ description = "Internal Server Error"
128+ ),
129+ @ ApiResponse (
130+ responseCode = "501" ,
131+ description = "This authentication method is only supported by the OpenTSDB database." ,
132+ content = @ Content (mediaType = MediaType .APPLICATION_JSON ,
133+ schema = @ Schema (type = "object" , implementation = StringToClassMapItem .class ),
134+ examples = @ ExampleObject (value = "{\" status\" :501," +
135+ "\" message\" :\" Basic Auth is not supported.\" }" ))
136+ )
137+ }
138+ )
139+ public Response postCredentials (Credentials credentials ) throws WebAppException
140+ {
141+ return doLogin (credentials );
142+ }
143+
81144 @ POST
82145 @ Path ("credentials" )
83146 @ Consumes (MediaType .APPLICATION_FORM_URLENCODED )
@@ -142,20 +205,18 @@ public Response postCredentials(@FormParam("username") String username,
142205 Credentials credentials = new Credentials ();
143206 credentials .setUsername (username );
144207 credentials .setPassword (password );
145- TimeSeriesDb db = getLegacyTimeseriesDB ();
146- if (!db .isOpenTSDB ())
147- {
148- throw new ServerErrorException ("Basic Auth is not supported" , Response .Status .NOT_IMPLEMENTED );
149- }
208+ return doLogin (credentials );
209+ }
150210
211+ private Response doLogin (Credentials credentials ) throws WebAppException
212+ {
151213 //If credentials are null, Authorization header will be checked.
152- if (credentials ! = null )
214+ if (credentials = = null )
153215 {
154- verifyCredentials ( credentials );
216+ throw newAuthException ( );
155217 }
156-
157- String authorizationHeader = httpHeaders .getHeaderString (HttpHeaders .AUTHORIZATION );
158- credentials = getCredentials (credentials , authorizationHeader );
218+
219+ verifyCredentials (credentials );
159220 validateDbCredentials (credentials );
160221 Set <OpenDcsApiRoles > roles = getUserRoles (credentials .getUsername ());
161222 OpenDcsPrincipal principal = new OpenDcsPrincipal (credentials .getUsername (), roles );
@@ -196,75 +257,11 @@ private static void verifyCredentials(Credentials credentials)
196257 }
197258 }
198259
199- private static Credentials getCredentials (Credentials postBody , String authorizationHeader )
200- {
201- if (postBody != null )
202- {
203- return postBody ;
204- }
205- if (authorizationHeader == null || authorizationHeader .isEmpty ())
206- {
207- throw newAuthException ();
208- }
209- return parseAuthorizationHeader (authorizationHeader );
210- }
211-
212260 private static BadRequestException newAuthException ()
213261 {
214262 return new BadRequestException ("Credentials not provided." );
215263 }
216264
217- private static Credentials parseAuthorizationHeader (String authString )
218- {
219- String [] authHeaders = authString .split ("," );
220- for (String header : authHeaders )
221- {
222- String trimmedHeader = header .trim ();
223- LOGGER .debug (MODULE + ".makeToken authHdr = {}" , trimmedHeader );
224- if (trimmedHeader .startsWith ("Basic" ))
225- {
226- return extractCredentials (trimmedHeader .substring (6 ).trim ());
227- }
228- }
229- throw newAuthException ();
230- }
231-
232- private static Credentials extractCredentials (String base64Credentials )
233- {
234- String decodedCredentials = new String (Base64 .getDecoder ().decode (base64Credentials .getBytes ()));
235- String [] parts = decodedCredentials .split (":" , 2 );
236-
237- if (parts .length < 2 || parts [0 ] == null || parts [1 ] == null
238- || parts [0 ].isEmpty () || parts [1 ].isEmpty ())
239- {
240- throw newAuthException ();
241- }
242-
243- Credentials credentials = new Credentials ();
244- credentials .setUsername (parts [0 ]);
245- credentials .setPassword (parts [1 ]);
246-
247- LOGGER .info (MODULE + ".checkToken found tokstr in header." );
248- return credentials ;
249- }
250-
251- private String getDatabaseUrl () throws WebAppException
252- {
253- DataSource dataSource = (DataSource ) context .getAttribute (DATA_SOURCE_ATTRIBUTE_KEY );
254- try (Connection poolCon = dataSource .getConnection ())
255- {
256- // The only way to verify that user/pw is valid is to attempt to establish a connection:
257- // This should eventually be moved to a users table
258- DatabaseMetaData metaData = poolCon .getMetaData ();
259- return metaData .getURL ();
260- }
261- catch (SQLException e )
262- {
263- throw new WebAppException (HttpServletResponse .SC_INTERNAL_SERVER_ERROR ,
264- "Failed to obtain database URL." , e );
265- }
266- }
267-
268265 private void validateDbCredentials (Credentials creds ) throws WebAppException
269266 {
270267
0 commit comments