diff --git a/spec/controllers/api_key_spec.cr b/spec/controllers/api_key_spec.cr index 16d76f8b..5d115ba9 100644 --- a/spec/controllers/api_key_spec.cr +++ b/spec/controllers/api_key_spec.cr @@ -18,5 +18,50 @@ module PlaceOS::Api describe "scopes" do Spec.test_controller_scope(ApiKeys) end + + describe "API key expiry", tags: "expiry" do + it "rejects expired API keys with 401" do + user, headers = Spec::Authentication.x_api_authentication + api_key = PlaceOS::Model::ApiKey.where(name: user.email.to_s).first + api_key.expires_at = Time.utc + 1.second + api_key.save! + sleep 1.5 + + result = client.get(path: ApiKeys.base_route + "inspect", headers: headers) + result.status_code.should eq 401 + end + + it "accepts non-expired API keys" do + user, headers = Spec::Authentication.x_api_authentication + api_key = PlaceOS::Model::ApiKey.where(name: user.email.to_s).first + api_key.expires_at = Time.utc + 1.hour + api_key.save! + + result = client.get(path: ApiKeys.base_route + "inspect", headers: headers) + result.status_code.should eq 200 + end + + it "accepts API keys with no expiry set" do + user, headers = Spec::Authentication.x_api_authentication + api_key = PlaceOS::Model::ApiKey.where(name: user.email.to_s).first + api_key.expires_at = nil + api_key.save! + + result = client.get(path: ApiKeys.base_route + "inspect", headers: headers) + result.status_code.should eq 200 + end + + it "shows expired keys in index listing" do + user, _ = Spec::Authentication.x_api_authentication + api_key = PlaceOS::Model::ApiKey.where(name: user.email.to_s).first + api_key.expires_at = Time.utc + 1.second + api_key.save! + sleep 1.5 + + admin_headers = Spec::Authentication.headers + result = client.get(path: ApiKeys.base_route, headers: admin_headers) + result.status_code.should eq 200 + end + end end end diff --git a/src/placeos-rest-api/utilities/current-user.cr b/src/placeos-rest-api/utilities/current-user.cr index 03c2ac00..20fb6e27 100644 --- a/src/placeos-rest-api/utilities/current-user.cr +++ b/src/placeos-rest-api/utilities/current-user.cr @@ -23,12 +23,15 @@ module PlaceOS::Api if token = request.headers["X-API-Key"]? || params["api-key"]? || cookies["api-key"]?.try(&.value) begin api_key = ::PlaceOS::Model::ApiKey.find_key!(token) + raise Error::Unauthorized.new "API key has expired" if api_key.expired? user_token = api_key.build_jwt Log.context.set(api_key_id: api_key.id, api_key_name: api_key.name) ensure_matching_domain(user_token) @user_token = user_token @current_user = ::PlaceOS::Model::User.find(user_token.id) return user_token + rescue e : Error::Unauthorized + raise e rescue e Log.warn(exception: e) { {message: "bad or unknown X-API-Key", action: "authorize!"} } raise Error::Unauthorized.new "unknown X-API-Key"