oncall icon indicating copy to clipboard operation
oncall copied to clipboard

Authenticate to API via API key

Open jonsger opened this issue 5 years ago • 1 comments

Hi,

it would be nice to authenticate to the API via an API key. At the moment you have to use a Cookie and the X-CSRF-TOKEN. This is not so nice, because they could become invalid after the session ends.

An alternative would be a cookie and CSRF-token who never get's invalid, but I would still prefer a proper API key :)

jonsger avatar Jul 26 '19 12:07 jonsger

Hi, @jonsger Oncall use hmac auth. See tests https://github.com/linkedin/oncall/blob/master/test/test_auth.py#L50

Example client code:

import json
import time
import hmac
import base64
import hashlib

import requests


class Oncall:
    def __init__(self, api_url, application, key):
        self.api_url = api_url
        self.application = application
        self._key = key

        self.session = requests.session()

    def _sign_request(self, method, path, body):
        window = int(time.time()) // 5
        text = '%s %s %s %s' % (window, method, path, body)
        hashed = hmac.new(self._key.encode(), text.encode('utf-8'), hashlib.sha512)
        return base64.urlsafe_b64encode(hashed.digest()).decode('utf-8')

    def raw(self, method, uri, params=None, data=None):
        url = self.api_url + uri
        signature = self._sign_request(
            method, '/' + url.split('/', maxsplit=3)[-1], json.dumps(data)
        )
        return self.session.request(
            method,
            url,
            headers={
                'AUTHORIZATION': f'hmac {self.application}:{signature}'
            },
            params=params,
            json=data
        )

Usage: 1 add new application via sql

INSERT INTO oncall.application (id,name,`key`)
VALUES (1,'test_app,'test_key');

2 use client from example

client = Oncall('http://127.0.0.1:8080/api/v0', 'test_app', 'test_key')
payload = {
    "mode": "sms",
    "only_if_involved": True,
    "roles":
        ["primary", "secondary", "shadow", "manager", "vacation", "unavailable"],
    "type": "event_created",
    "team": "Test Team",
    "viewType": "notification"
}
print(
    client.raw('POST', '/users/root/notifications', data=payload).json()
)

DesSolo avatar Jun 08 '22 10:06 DesSolo