{"id":23859218,"url":"https://github.com/openconext/stepup-tiqr","last_synced_at":"2025-09-08T07:30:50.332Z","repository":{"id":33631805,"uuid":"37284129","full_name":"OpenConext/Stepup-tiqr","owner":"OpenConext","description":"tiqr IdP for step-up authentication","archived":false,"fork":false,"pushed_at":"2025-08-12T11:57:24.000Z","size":5446,"stargazers_count":3,"open_issues_count":23,"forks_count":2,"subscribers_count":12,"default_branch":"main","last_synced_at":"2025-08-12T13:31:52.976Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OpenConext.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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,"zenodo":null}},"created_at":"2015-06-11T20:23:11.000Z","updated_at":"2025-08-12T11:15:17.000Z","dependencies_parsed_at":"2023-02-10T01:46:32.163Z","dependency_job_id":"a9091c9d-129d-4379-84a8-87695ed31233","html_url":"https://github.com/OpenConext/Stepup-tiqr","commit_stats":null,"previous_names":[],"tags_count":131,"template":false,"template_full_name":null,"purl":"pkg:github/OpenConext/Stepup-tiqr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenConext%2FStepup-tiqr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenConext%2FStepup-tiqr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenConext%2FStepup-tiqr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenConext%2FStepup-tiqr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OpenConext","download_url":"https://codeload.github.com/OpenConext/Stepup-tiqr/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenConext%2FStepup-tiqr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274152121,"owners_count":25231285,"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","status":"online","status_checked_at":"2025-09-08T02:00:09.813Z","response_time":121,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":"2025-01-03T03:32:58.605Z","updated_at":"2025-09-08T07:30:49.910Z","avatar_url":"https://github.com/OpenConext.png","language":"PHP","readme":"Stepup-tiqr\n===========\n[![CI/CD quality assurance](https://github.com/OpenConext/Stepup-tiqr/actions/workflows/test-integration.yml/badge.svg)](https://github.com/OpenConext/Stepup-tiqr/actions/workflows/test-integration.yml)\n[![CI/CD functional tests](https://github.com/OpenConext/Stepup-tiqr/actions/workflows/test-acceptance.yml/badge.svg)](https://github.com/OpenConext/Stepup-tiqr/actions/workflows/test-acceptance.yml)\n\nGSSP implementation of Tiqr. [https://tiqr.org/documentation/](https://tiqr.org/documentation/)\n\nProject is based on example GSSP project [https://github.com/OpenConext/Stepup-gssp-example](https://github.com/OpenConext/Stepup-gssp-example)\n\nLocale user preference\n----------------------\n\nThe default locale is based on the user agent. When the user switches its locale the selected preference is stored inside a\nbrowser cookie (stepup_locale). The cookie is set on naked domain of the requested domain (for tiqr.dev.openconext.local this is dev.openconext.local).\n\nAuthentication and registration flows\n-------------------------------------\n\nThe application provides internal (SpBundle) and a remote service provider. Instructions for this are given \non the homepage of this Tiqr project [Homepage](https://tiqr.dev.openconext.local/).\n\n![flow](docs/flow.png)\n\u003c!---\nregenerate docs/flow.png with `plantum1 README.md` or with http://www.plantuml.com/plantuml\n@startuml docs/flow\nactor User\nparticipant \"Service provider\" as SP\nbox \"Stepup Tiqr\"\nparticipant \"GSSP Bundle\" as IdP\nparticipant \"Tiqr implementation\" as TiqrSF\nend box\nUser -\u003e SP: Register/Authenticate\nSP -\u003e IdP: Send AuthnRequest\nactivate IdP\nIdP -\u003e TiqrSF: Redirect to SecondFactor endpoint\nTiqrSF -\u003e TiqrSF: \u003cTiqr logic\u003e\nTiqrSF -\u003e IdP: Redirect to SSO Return endpoint\nIdP -\u003e SP: AuthnRequest response\ndeactivate IdP\nSP -\u003e User: User registered/Authenticated\n@enduml\n---\u003e\n\nTiqr registration\n-----------------\n\n![flow](docs/tiqr_registration.png)\n\u003c!---\nregenerate docs/tiqr_registration.png with `plantum1 README.md` or with http://www.plantuml.com/plantuml\n@startuml docs/tiqr_registration\nactor User\nparticipant \"Website\" as Site\nparticipant \"App\" as App\nparticipant \"Api\" as Api\nactivate Site\nSite -\u003e User: Show QR code\nApp -\u003e Site: Scan the registration code\ndeactivate Site\nactivate App\nApp -\u003e Api: Request the metadata endpoint \nApp -\u003e User: Asks for verification code\nApp -\u003e Api: Registers user with secret and OTP\ndeactivate App\nactivate Site\nSite -\u003e Api: Asks the Api if the user is registered\nSite -\u003e User: Registration done\ndeactivate Site\n@enduml\n---\u003e\n\nDevelopment environment\n======================\n\nTo get started, first setup the development environment. The dev env is a virtual machine. Every task described here is required to run\nfrom that machine.  \n\nRequirements\n-------------------\n- ansible 2.x\n- vagrant 1.9.x\n- vagrant-hostsupdater\n- Virtualbox\n- ansible-galaxy\n\nInstall\n=======\n\nSee one of the following guides:\n\n[Development guide](docs/development.md)\n\n[Production installation](docs/deployment.md)\n\nTests and metrics\n======================\n\nTo run all required test you can run the following commands from the dev env:\n\n```bash \n    composer test \n    composer behat\n```\n\nEvery part can be run separately. Check \"scripts\" section of the composer.json file for the different options.\n\nTest Tiqr Api's\n---------------\n\nDemo sp is available on  [https://tiqr.dev.openconext.local/demo/sp]()\n\nFetch registration link automatically from /app_dev.php/registration/qr/dev\n\n``` ./bin/console test:registration \u003c./qr_file.png\u003e```  \n\n``` ./bin/console test:authentication \u003c./qr_file.png\u003e```  \n\nAuthentication can also be done in 'offline' mode, so you need to fill in your 'one time password'.\n\n``` ./bin/console test:authentication --offline=true ./\u003cqr_file.png\u003e```  \n\nUser storage\n============\nCurrently we support three user storage solutions. Which are file system storage, ldap and database storage. The \nfilesystem storage is used by default and stores the registered users in the `/var/userdb.json` file. \n\nDatabase storage\n----------------\nTo use the database storage you will need to change some settings:\n\nIn the `parametes.yml`, in the `tiqr_library_options.storage.userstorage` section configure: \n\n```yaml\ntiqr_library_options:        \n    storage:\n        userstorage:\n            type: pdo\n            arguments:\n                table: user\n                dsn: 'mysql:host=tiqr.stepup.example.com;dbname=tiqr'\n                username: tiqr-user\n                password: tiqr-secret\n```\n\nThe database schema can be found here: `app/Resources/db/mysql-create-tables.sql`\n\nFilesystem storage\n------------------\nOr if you want to use the filesystem storage use this:\n\n```yaml\ntiqr_library_options:        \n    storage:\n        userstorage:\n            type: 'file'\n            arguments:\n              path: '/tmp'\n              encryption: 'dummy' # mcrypt is also supported, dummy will not encrypt the entries in the user storage file\n```\n\nLDAP storage\n------------\nFinally to use the LDAP backend provide the following options:\n\n```yaml\ntiqr_library_options:        \n    storage:\n        userstorage:\n            type: 'ldap'\n            # The argument values equal the default values set when the arguments are omitted. So all arguments are\n            # optional.\n            arguments:\n                userClass: 'tiqrPerson'\n                dnPattern: '%s'\n                idAttr: 'dn'\n                displayNameAttr: 'sn'\n                secretAttr: 'tiqrSecret'\n                notificationTypeAttr: 'tiqrNotificationType'        \n                notificationAddressAttr: 'tiqrNotificationAddress'        \n                isBlockedAttr: 'tiqrIsBlocked'\n                loginAttemptsAttr: 'tiqrLoginAttempts'  \n                temporaryBlockAttemptsAttr: 'tiqrTemporaryBlockAttempts'\n                temporaryBlockTimestampAttr: 'tiqrTemporaryBlockTimestamp'\n                attributes: null\n```\n\n# Release strategy\nPlease read: https://github.com/OpenConext/Stepup-Deploy/wiki/Release-Management fro more information on the release strategy used in Stepup projects.\n\n# How the Stepup-tiqr uses the Tiqr library\nThe Tiqr server's purpose is to facilitate Tiqr authentications. In doing so communicating with the Tiqr app. Details about this communication flow can be found in the flow above. Here you will find a communication diagram for enrollment and authentication.\n\nThe following code examples show some of the concepts that are used during authentication from the web frontend. It does not include the communication with the Tiqr client (app).\n\n```php\n# 1. The name id (username) of the user is used to identify that specific user in Tiqr. \n#    In the case of Stepup-Tiqr (SAML based) we get the NameId from the SAML 2.0 AuthnRequest\n#\n# Example below is pseudocode you might write in your controller dealing with an authentication request\n$nameId = $this-\u003eauthenticationService-\u003egetNameId();\n\n# The request id of the SAML AuthnRequest message, used to match the originating authentication request with the Tiqr authentication\n$requestId = $this-\u003eauthenticationService-\u003egetRequestId();\n```\n\n```php\n# 2. Next you can do some verifications on the user, is it found in tiqr-server user storage?\n#    Is it not locked out temporarily?\n#\n# Example below is pseudocode you might write in your controller dealing with an authentication request\n$user = $this-\u003euserRepository-\u003egetUser($nameId);\nif ($this-\u003eauthenticationRateLimitService-\u003eisBlockedTemporarily($user)) {\n    throw new Exception('You are locked out of the system');\n}\n\n$this-\u003estartAuthentication($nameId, $requestId)\npublic function startAuthentication($nameId, $requestId)\n{\n    # Authentication is started by providing the NameId and the PHP session id\n    $sessionKey = $this-\u003etiqrService-\u003estartAuthenticationSession($nameId, $this-\u003esession-\u003egetId());\n    # The Service (Tiqr_Service) generates a session key which is stored in the state storage, but also returned to\n    # persist in the Tiqr server implementation. \n    $this-\u003esession-\u003eset('sessionKey', $sessionKey);\n    $this-\u003estoreRequestIdForNameId($sessionKey, $requestId);\n    # Creates an authentication challenge URL. It links directly to the application \n    return $this-\u003etiqrService-\u003egenerateAuthURL($sessionKey);\n}\n```\n\n```php\n# 3. The tiqr server implementation now must wait for the Tiqr App to finalize its authentication with the user.\n#    In the Stepup-Tiqr implementation, we do this by polling the tiqr server for the atuthentication status.\n# Example below is pseudocode\n\n# Javascript\nfunction pollTiqrStatus() {\n    getTiqrStatus()\n    setTimeout(refresh, 5000);\n}\npollTiqrStatus();\n\n# In the PHP application:\n$isAuthenticated = $this-\u003etiqrService-\u003egetAuthenticatedUser($this-\u003esession-\u003egetId());\nif ($isAuthenticated) {\n    # Your controller can now go to the next action, maybe send back a successful SamlResponse, or signal otherwise\n    # that the authentication succeeded. \n    return $successResponse;\n}\n# And deal with the non happy flow\n\nif ($isExpired) {\n    return $errorResponse;\n}\n\nif ($otherErrorConddition) {\n    # ...\n}\n```\n\nOther resources\n===============\n\n - [Developer documentation](docs/index.md)\n - [Issue tracker](https://www.pivotaltracker.com/n/projects/1163646)\n - [License](LICENSE)\n - [Tiqr library](https://github.com/SURFnet/tiqr-server-libphp)\n - [Library documentation](https://tiqr.org/documentation/) \n - [Tiqr config parameters](https://github.com/SURFnet/simplesamlphp-module-authtiqr)\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenconext%2Fstepup-tiqr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenconext%2Fstepup-tiqr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenconext%2Fstepup-tiqr/lists"}