{"id":21819353,"url":"https://github.com/dflydev/dflydev-hawk","last_synced_at":"2025-04-06T05:18:00.191Z","repository":{"id":9316309,"uuid":"11158407","full_name":"dflydev/dflydev-hawk","owner":"dflydev","description":"Hawk — A PHP Implementation","archived":false,"fork":false,"pushed_at":"2024-03-05T08:26:02.000Z","size":293,"stargazers_count":67,"open_issues_count":6,"forks_count":19,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-30T04:08:59.436Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dflydev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-07-03T18:39:03.000Z","updated_at":"2023-04-17T23:08:33.000Z","dependencies_parsed_at":"2024-06-18T13:42:58.469Z","dependency_job_id":"636c0973-3fef-4886-9501-58e9aa8187df","html_url":"https://github.com/dflydev/dflydev-hawk","commit_stats":{"total_commits":47,"total_committers":4,"mean_commits":11.75,"dds":0.08510638297872342,"last_synced_commit":"937fe56288e3da60127116284fe2fd50db2174b8"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dflydev%2Fdflydev-hawk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dflydev%2Fdflydev-hawk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dflydev%2Fdflydev-hawk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dflydev%2Fdflydev-hawk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dflydev","download_url":"https://codeload.github.com/dflydev/dflydev-hawk/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247436362,"owners_count":20938547,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-27T16:18:36.685Z","updated_at":"2025-04-06T05:18:00.067Z","avatar_url":"https://github.com/dflydev.png","language":"PHP","funding_links":[],"categories":["身份验证","身份验证( Authentication and Authorization )","Authentication","身份验证和授权 Authentication and Authorization"],"sub_categories":[],"readme":"Hawk — A PHP Implementation\n===========================\n\n\u003e Hawk is an HTTP authentication scheme using a message authentication code\n\u003e (MAC) algorithm to provide partial HTTP request cryptographic verification.\n\u003e — [hawk README][0]\n\n\nInstallation\n------------\n\nThrough [Composer][1] as [dflydev/hawk][2].\n\n\nClient\n------\n\n### Building a Client\n\nThe `Client` has a few required dependencies. It is generally easier to\nconstruct a `Client` by using the `ClientBuilder`. A `Client` can be built\nwithout setting anything to get sane defaults.\n\n#### Simple ClientBuilder Example\n\n```php\n\u003c?php\n\n// Simple example\n$client = Dflydev\\Hawk\\Client\\ClientBuilder::create()\n    -\u003ebuild()\n```\n\n#### Complete ClientBuilderExample\n\n```php\n\u003c?php\n\n// A complete example\n$client = Dflydev\\Hawk\\Client\\ClientBuilder::create()\n    -\u003esetCrypto($crypto)\n    -\u003esetTimeProvider($timeProvider)\n    -\u003esetNonceProvider($nonceProvider)\n    -\u003esetLocaltimeOffset($localtimeOffset)\n    -\u003ebuild()\n```\n\n### Creating a Request\n\nIn order for a client to be able to sign a request, it needs to know the\ncredentials for the user making the request, the URL, method, and optionally\npayload and content type of the request.\n\nAll available options include:\n\n * **payload**: The body of the request\n * **content_type**: The content-type for the request\n * **nonce**: If a specific nonce should be used in favor of one being generated\n   automatically by the nonce provider.\n * **ext**: An ext value specific for this request\n * **app**: The app for this request ([Oz][3] specific)\n * **dlg**: The delegated-by value for this request ([Oz][3] specific)\n\n\n#### Create Request Example\n\n```php\n\u003c?php\n\n$request = $client-\u003ecreateRequest(\n    $credentials,\n    'http://example.com/foo/bar?whatever',\n    'POST',\n    array(\n        'payload' =\u003e 'hello world!',\n        'content_type' =\u003e 'text/plain',\n    )\n);\n\n// Assuming a hypothetical $headers object that can be used to add new headers\n// to an outbound request, we can add the resulting 'Authorization' header\n// for this Hawk request by doing:\n$headers-\u003eset(\n    $request-\u003eheader()-\u003efieldName(), // 'Authorization'\n    $request-\u003eheader()-\u003efieldValue() // 'Hawk id=\"12345\", mac=\"ad8c9f', ...'\n);\n\n```\n\n#### The Client Request Object\n\nThe `Request` represents everything the client needs to know about a request\nincluding a header and the artifacts that were used to create the request.\n\n * **header()**: A `Header` instance that represents the request\n * **artifacts()**: An `Artifacts` instance that contains the values that were\n   used in creating the request\n\nThe **header** is required to be able to get the properly formatted Hawk\nauthorization header to send to the server. The **artifacts** are useful in the\ncase that authentication will be done on the server response.\n\n\n### Authenticate Server Response\n\nHawk provides the ability for the client to authenticate a server response to\nensure that the response sent back is from the intended target.\n\nAll available options include:\n\n * **payload**: The body of the response\n * **content_type**: The content-type for the response\n\n\n#### Authenticate Response Example\n\n```php\n\u003c?php\n\n// Assuming a hypothetical $headers object that can be used to get headers sent\n// back as the response of a user agent request, we can get the value for the\n// 'Server-Authorization' header.\n$header = $headers-\u003eget('Server-Authorization');\n\n// We need to use the original credentials, the original request, the value\n// for the 'Server-Authorization' header, and optionally the payload and\n// content type of the response from the server.\n$isAuthenticatedResponse = $client-\u003eauthenticate(\n    $credentials,\n    $request,\n    $header,\n    array(\n        'payload' =\u003e '{\"message\": \"good day, sir!\"}',\n        'content_type' =\u003e 'application/json',\n    )\n);\n```\n\n### Complete Client Example\n\n```php\n\u003c?php\n\n// Create a set of Hawk credentials\n$credentials = new Dflydev\\Hawk\\Credentials\\Credentials(\n    'afe89a3x',  // shared key\n    'sha256',    // default: sha256\n    '12345'      // identifier, default: null\n);\n\n// Create a Hawk client\n$client = Dflydev\\Hawk\\Client\\ClientBuilder::create()\n    -\u003ebuild();\n\n// Create a Hawk request based on making a POST request to a specific URL\n// using a specific user's credentials. Also, we're expecting that we'll\n// be sending a payload of 'hello world!' with a content-type of 'text/plain'.\n$request = $client-\u003ecreateRequest(\n    $credentials,\n    'http://example.com/foo/bar?whatever',\n    'POST',\n    array(\n        'payload' =\u003e 'hello world!',\n        'content_type' =\u003e 'text/plain',\n    )\n);\n\n// Ask a really useful fictional user agent to make a request; note that the\n// request we are making here matches the details that we told the Hawk client\n// about our request.\n$response = Fictional\\UserAgent::makeRequest(\n    'POST',\n    'http://example.com/foo/bar?whatever',\n    array(\n        'content_type' =\u003e 'text/plain',\n        $request-\u003eheader()-\u003efieldName() =\u003e $request-\u003eheader()-\u003efieldValue(),\n    ),\n    'hello world!'\n);\n\n// This part is optional but recommended! At this point if we have a successful\n// response we could just look at the content and be done with it. However, we\n// are given the tools to authenticate the response to ensure that the response\n// we were given came from the server we were expecting to be talking to.\n$isAuthenticatedResponse = $client-\u003eauthenticate(\n    $credentials,\n    $request,\n    $response-\u003eheaders-\u003eget('Server-Authorization'),\n    array(\n        'payload' =\u003e $response-\u003egetContent(),\n        'content_type' =\u003e $response-\u003eheaders-\u003eget('content-type'),\n    )\n);\n\nif (!$isAuthenticatedResponse) {\n    die(\"The server did a very bad thing...\");\n}\n\n// Huzzah!\n```\n\n\n### Bewit\n\nHawk supports a method for granting third-parties temporary access to individual\nresources using a query parameter called bewit.\n\nThe return value is a string that represents the bewit. This string should be\nadded to a requested URI by appending it to the end of the URI. If the URI has\nquery parameters already, the bewit should have `\u0026bewit=` appended to the front\nof it. If the URI does not have query parameters already, the bewit should\nhave `?bewit=` appended to the front of it.\n\n#### Client Bewit Example\n\n```php\n\u003c?php\n\n$bewit = $client-\u003ecreateBewit(\n    $credentials,\n    'https://example.com/posts?foo=bar',\n    300 // ttl in seconds\n);\n```\n\nServer\n------\n\n### Building a Server\n\nThe `Server` has a few required dependencies. It is generally easier to\nconstruct a `Server` by using the `ServerBuilder`. A `Server` can be built\nwithout setting anything but the credentials provider to get sane defaults.\n\n#### Simple ServerBuilder Example\n\n```php\n\u003c?php\n\n$credentialsProvider = function ($id) {\n    if ('12345' === $id) {\n        return new Dflydev\\Hawk\\Credentials\\Credentials(\n            'afe89a3x',  // shared key\n            'sha256',    // default: sha256\n            '12345'      // identifier, default: null\n        );\n    }\n};\n\n// Simple example\n$server = Dflydev\\Hawk\\Server\\ServerBuilder::create($credentialsProvider)\n    -\u003ebuild()\n```\n\n#### Complete ServerBuilderExample\n\n```php\n\u003c?php\n\n$credentialsProvider = function ($id) {\n    if ('12345' === $id) {\n        return new Dflydev\\Hawk\\Credentials\\Credentials(\n            'afe89a3x',  // shared key\n            'sha256',    // default: sha256\n            '12345'      // identifier, default: null\n        );\n    }\n};\n\n// A complete example\n$server = Dflydev\\Hawk\\Server\\ServerBuilder::create($credentialsProvider)\n    -\u003esetCrypto($crypto)\n    -\u003esetTimeProvider($timeProvider)\n    -\u003esetNonceValidator($nonceValidator)\n    -\u003esetTimestampSkewSec($timestampSkewSec)\n    -\u003esetLocaltimeOffsetSec($localtimeOffsetSec)\n    -\u003ebuild()\n```\n\n### Authenticating a Request\n\nIn order for a server to be able to authenticate a request, it needs to be able\nto build the same MAC that the client did. It does this by getting the same\ninformation about the request that the client knew about when it signed the\nrequest.\n\nIn particular, the authorization header should include the ID. This ID is used\nto retrieve the credentials (notably the key) in order to calculate the MAC\nbased on the rest of the request information.\n\n#### Authenticate Example\n\n```php\n\u003c?php\n\n// Get the authorization header for the request; it should be in the form\n// of 'Hawk id=\"...\", mac=\"...\", [...]'\n$authorization = $headers-\u003eget('Authorization');\n\ntry {\n    $response = $server-\u003eauthenticate(\n        'POST',\n        'example.com',\n        80,\n        '/foo/bar?whatever',\n        'text/plain',\n        'hello world!'\n        $authorization\n    );\n} catch(Dflydev\\Hawk\\Server\\UnauthorizedException $e) {\n    // If authorization is incorrect (invalid mac, etc.) we can catch an\n    // unauthorized exception.\n    throw $e;\n}\n\n// The credentials associated with this request. This is where one could access\n// the ID for the user that made this request.\n$credentials = $response-\u003ecredentials();\n\n// The artifacts associated with this request. This is where one could access\n// things like the 'ext', 'app', and 'dlg' values sent with the request.\n$artifacts = $response-\u003eartifacts();\n```\n\n#### The Server Response Object\n\nThe `Response` represents everything the server needs to know about a request\nincluding the credentials and artifacts that are associated with the request.\n\n * **credentials()**\n * **artifacts()**\n\n\n### Creating a Response Header\n\nHawk provides the ability for the server to sign the response to provide the\nclient with a way to authenticate a server response.\n\nAll available options include:\n\n * **payload**: The body of the request\n * **content_type**: The content-type for the request\n * **ext**: An ext value specific for this request\n\n\n#### Create Response Header Example\n\n```php\n\u003c?php\n\n// Using the same credentials and artifacts from the server authenticate\n// response, we can create a 'Server-Authorization' header.\n$header = $server-\u003ecreateHeader($credentials, $artifacts, array(\n    'payload' =\u003e '{\"message\": \"good day, sir!\"}',\n    'content_type' =\u003e 'application/json',\n));\n\n// Set the header using PHP's header() function.\nheader(sprintf(\"%s: %s\", $header-\u003efieldName(), $header-\u003efieldValue()));\n```\n\n### Complete Server Example\n\n```php\n\u003c?php\n\n// Create a simple credentials provider\n$credentialsProvider = function ($id) {\n    if ('12345' === $id) {\n        return new Dflydev\\Hawk\\Credentials\\Credentials(\n            'afe89a3x',  // shared key\n            'sha256',    // default: sha256\n            '12345'      // identifier, default: null\n        );\n    }\n};\n\n// Create a Hawk server\n$server = Dflydev\\Hawk\\Server\\ServerBuilder::create($credentialsProvider)\n    -\u003ebuild()\n\n// Get the authorization header for the request; it should be in the form\n// of 'Hawk id=\"...\", mac=\"...\", [...]'\n$authorization = $headers-\u003eget('Authorization');\n\ntry {\n    $response = $server-\u003eauthenticate(\n        'POST',\n        'example.com',\n        80,\n        '/foo/bar?whatever',\n        'text/plain',\n        'hello world!'\n        $authorization\n    );\n} catch(Dflydev\\Hawk\\Server\\UnauthorizedException $e) {\n    // If authorization is incorrect (invalid mac, etc.) we can catch an\n    // unauthorized exception.\n    throw $e;\n}\n\n// Huzzah! Do something at this point with the request as we now know that\n// it is an authenticated Hawk request.\n//\n// ...\n//\n// Ok we are done doing things! Assume based on what we did we ended up deciding\n// the following payload and content type should be used:\n\n$payload = '{\"message\": \"good day, sir!\"}';\n$contentType = 'application/json';\n\n// Create a Hawk header to sign our response\n$header = $server-\u003ecreateHeader($credentials, $artifacts, array(\n    'payload' =\u003e $payload,\n    'content_type' =\u003e $contentType,\n));\n\n// Send some headers\nheader(sprintf(\"%s: %s\", 'Content-Type', 'application/json'));\nheader(sprintf(\"%s: %s\", $header-\u003efieldName(), $header-\u003efieldValue()));\n\n// Output our payload\nprint $payload;\n```\n\n\n### Bewit\n\nHawk supports a method for granting third-parties temporary access to individual\nresources using a query parameter called bewit.\n\nBewit authentication should only occur for `GET` and `HEAD` requests. The return\nvalue of an authenticated bewit is a Server Response object.\n\n#### Server Bewit Example\n\n```php\n\u003c?php\n\n$response = $server-\u003eauthenticateBewit(\n    'example.com',\n    443,\n    '/posts?bewit=ZXhxYlpXdHlrRlpJaDJEN2NYaTlkQVwxMzY4OTk2ODAwXE8wbWhwcmdvWHFGNDhEbHc1RldBV3ZWUUlwZ0dZc3FzWDc2dHBvNkt5cUk9XA'\n);\n```\n\n\nCrypto\n------\n\n### Dflydev\\Hawk\\Crypto\\Crypto\n\nTools for calculation of and comparison of MAC values.\n\n * **calculatePayloadHash($payload, $algorithm, $contentType)**\n * **calculateMac($type, CredentialsInterface $credentials, Artifacts $attributes)**\n * **calculateTsMac($ts, CredentialsInterface $credentials)**\n * **fixedTimeComparison($a, $b)**\u003cbr\u003e\n   Used to ensure that the comparing two strings will always take the same amount\n   of time regardless of whether they are the same or not.\n\n\n### Dflydev\\Hawk\\Crypto\\Artifacts\n\nA container for all of the pieces of data that may go into the creation of a\nMAC.\n\n\nCredentials\n-----------\n\n### Dflydev\\Hawk\\Credentials\\CredentialsInterface\n\nRepresents a valid set of credentials.\n\n * **key()**: Used to calculate the MAC\n * **algorithm()**: The algorithm used to calculate hashes\n * **id()**: An identifier (e.g. username) for whom the key belongs\n\nIn some contexts only the key may be known.\n\n### Dflydev\\Hawk\\Credentials\\Credentials\n\nA simple implementation of `CredentialsInterface`.\n\n```php\n\u003c?php\n\n$credentials = new Dflydev\\Hawk\\Credentials\\Credentials(\n    $key,        // shared key\n    $algorithm,  // default: sha256\n    $id          // identifier, default: null\n);\n\n```\n\n\nHeader\n------\n\n### Dflydev\\Hawk\\Header\\Header\n\n * **fieldName()**: The name for the header field\n * **fieldValue()**: The value for the header field\n * **attributes()**: The attributes used to build the field value\n\n### Dflydev\\Hawk\\Header\\HeaderFactory\n\n * **create($fieldName, array $attributes = null)**\u003cbr\u003e\n   Creates a Hawk header for a given field name for a set of attributes.\n * **createFromString($fieldName, $fieldValue, array $requiredKeys = null)**\u003cbr\u003e\n   Creates a Hawk header for a given field name from a Hawk value string. For\n   example, 'Hawk id=\"foo\", mac=\"1234\"' would be an example of a Hawk value\n   string. This is useful for converting a header value coming in off the wire.\n\n   Throws:\n\n    * **Dflydev\\Hawk\\Header\\FieldValueParserException**\n    * **Dflydev\\Hawk\\Header\\NotHawkAuthorizationException**\n\n### Dflydev\\Hawk\\Header\\HeaderParser\n\n * **parseFieldValue($fieldValue, array $requiredKeys = null)**\u003cbr\u003e\n   Parses a field value string into an associative array of attributes.\n\n   Throws:\n\n    * **Dflydev\\Hawk\\Header\\FieldValueParserException**\n    * **Dflydev\\Hawk\\Header\\NotHawkAuthorizationException**\n\n### Dflydev\\Hawk\\Header\\FieldValueParserException\n\nIndicates that a string claims to be a Hawk string but it cannot be completely\nparsed. This is mostly a sign of a corrupted or malformed header value.\n\n### Dflydev\\Hawk\\Header\\NotHawkAuthorizationException\n\nIndicates that the string has nothing to do with Hawk. Currently means that the\nstring does not start with 'Hawk'.\n\n\nLicense\n-------\n\nMIT, see LICENSE.\n\n\nCommunity\n---------\n\nIf you have questions or want to help out, join us in **#dflydev** on\n**irc.freenode.net**.\n\n\n[0]: https://github.com/hueniverse/hawk\n[1]: http://getcomposer.org/\n[2]: http://packagist.org/packages/dflydev/hawk\n[3]: https://github.com/hueniverse/oz\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdflydev%2Fdflydev-hawk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdflydev%2Fdflydev-hawk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdflydev%2Fdflydev-hawk/lists"}