fixed apiRequiredLocal method
authorJustin Wind <justin.wind+git@gmail.com>
Fri, 31 Dec 2021 20:08:37 +0000 (12:08 -0800)
committerJustin Wind <justin.wind+git@gmail.com>
Fri, 31 Dec 2021 20:08:37 +0000 (12:08 -0800)
lib/authenticator.js
test/lib/authenticator.js

index efa3d844e7502cd024c6c99da830342dfe04954f..1cff2108f309e2ac51245070281e0ec346f6168c 100644 (file)
@@ -338,7 +338,8 @@ class Authenticator {
 
   /**
    * Require auth for an API endpoint.
-   * Check for valid local identifier in session, or Authentication header.
+   * Check for valid local identifier in Authorization header; optionally
+   * fall back to session cookie if no header provided.
    * Prompts for Basic auth if not valid.
    * @param {http.ClientRequest} req
    * @param {http.ServerResponse} res
@@ -346,12 +347,25 @@ class Authenticator {
    * @param {Boolean} sessionAlsoValid
    */
   async apiRequiredLocal(req, res, ctx, sessionAlsoValid = true) {
-    const validSession = sessionAlsoValid && this.sessionCheck(req, res, ctx, undefined, false, false);
+    const _scope = _fileScope('apiRequiredLocal');
+    this.logger.debug(_scope, 'called', { ctx, sessionAlsoValid });
+
+    // If a Authorization header was provided, never consider session as a fallback.
     const authorizationHeader = req.getHeader(Enum.Header.Authorization);
-    const validAuthorization = authorizationHeader && this.isValidAuthorization(authorizationHeader, ctx);
-    if (validSession || validAuthorization) {
-      return true;
+    if (authorizationHeader) {
+      if (await this.isValidAuthorization(authorizationHeader, ctx)) {
+        this.logger.debug(_scope, 'valid authorization', { ctx, sessionAlsoValid });
+        return true;
+      }
+    } else {
+      if (sessionAlsoValid
+      &&  await this.sessionCheck(req, res, ctx, undefined, false, false)) {
+        this.logger.debug(_scope, 'valid session', { ctx, sessionAlsoValid });
+        return true;
+      }
     }
+
+    this.logger.debug(_scope, 'invalid authorization', { ctx, sessionAlsoValid });
     this.requestBasic(res);
   }
 
index 3ab6fb34653d0189e5066c44ec4188c4544015bb..067d0cae7a889a1eded72506527e29f08d1bc161 100644 (file)
@@ -407,7 +407,7 @@ describe('Authenticator', function () {
   }); // sessionCheck
 
   describe('apiRequiredLocal', function () {
-    let req, res, ctx;
+    let req, res;
     beforeEach(function () {
       ctx = {};
       req = {
@@ -423,18 +423,39 @@ describe('Authenticator', function () {
       sinon.stub(authenticator, 'sessionCheck').resolves(false);
       sinon.stub(authenticator, 'isValidAuthorization').resolves(true);
       const result = await authenticator.apiRequiredLocal(req, res, ctx);
-      assert(authenticator.sessionCheck.called);
+      assert.strictEqual(result, true);
       assert(authenticator.isValidAuthorization.called);
+      assert(!authenticator.sessionCheck.called);
+    });
+    it('covers invalid basic auth', async function () {
+      req.getHeader.returns('Basic Zm9vOmJhcg==');
+      sinon.stub(authenticator, 'sessionCheck').resolves(false);
+      sinon.stub(authenticator, 'isValidAuthorization').resolves(false);
+      try {
+        await authenticator.apiRequiredLocal(req, res, ctx);
+        assert.fail(noExpectedException);
+      } catch (e) {
+        assert.strictEqual(e.statusCode, 401);
+        assert(!authenticator.sessionCheck.called);
+        assert(authenticator.isValidAuthorization.called);
+      }
+    });
+    it('covers missing basic auth, valid session', async function () {
+      req.getHeader.returns();
+      sinon.stub(authenticator, 'sessionCheck').resolves(true);
+      sinon.stub(authenticator, 'isValidAuthorization').resolves(false);
+      const result = await authenticator.apiRequiredLocal(req, res, ctx);
       assert.strictEqual(result, true);
+      assert(!authenticator.isValidAuthorization.called);
+      assert(authenticator.sessionCheck.called);
     });
-    it('requests basic auth when missing, ignores session', async function () {
+    it('covers missing basic auth, ignores session', async function () {
       req.getHeader.returns();
       sinon.stub(authenticator, 'isValidAuthorization').resolves(true);
       try {
         await authenticator.apiRequiredLocal(req, res, ctx, false);
         assert.fail(noExpectedException);
       } catch (e) {
-        console.log(e);
         assert.strictEqual(e.statusCode, 401);
         assert(!authenticator.sessionCheck.called);
         assert(!authenticator.isValidAuthorization.called);