{"id":18026822,"url":"https://github.com/yegor256/glogin","last_synced_at":"2026-04-23T16:01:29.794Z","repository":{"id":56874649,"uuid":"101776289","full_name":"yegor256/glogin","owner":"yegor256","description":"Login/logout via GitHub OAuth for your Ruby web app","archived":false,"fork":false,"pushed_at":"2026-04-21T09:09:27.000Z","size":513,"stargazers_count":13,"open_issues_count":8,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2026-04-21T11:18:18.073Z","etag":null,"topics":["github","oauth2","ruby","ruby-gem"],"latest_commit_sha":null,"homepage":"https://www.yegor256.com/2018/06/19/glogin.html","language":"Ruby","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/yegor256.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-08-29T15:23:31.000Z","updated_at":"2026-04-21T09:08:20.000Z","dependencies_parsed_at":"2023-11-06T08:25:55.274Z","dependency_job_id":"a5aeab49-6dec-4b0c-b99c-909ff1ebac74","html_url":"https://github.com/yegor256/glogin","commit_stats":{"total_commits":73,"total_committers":3,"mean_commits":"24.333333333333332","dds":0.0547945205479452,"last_synced_commit":"0afbf1968d4ba65893cc32a3c52b69eafe99f9fa"},"previous_names":[],"tags_count":37,"template":false,"template_full_name":null,"purl":"pkg:github/yegor256/glogin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yegor256%2Fglogin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yegor256%2Fglogin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yegor256%2Fglogin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yegor256%2Fglogin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yegor256","download_url":"https://codeload.github.com/yegor256/glogin/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yegor256%2Fglogin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32187404,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-23T15:28:30.493Z","status":"ssl_error","status_checked_at":"2026-04-23T15:28:29.972Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["github","oauth2","ruby","ruby-gem"],"created_at":"2024-10-30T08:08:11.010Z","updated_at":"2026-04-23T16:01:29.785Z","avatar_url":"https://github.com/yegor256.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OAuth Login via GitHub Made Simple\n\n[![DevOps By Rultor.com](https://www.rultor.com/b/yegor256/glogin)](https://www.rultor.com/p/yegor256/glogin)\n[![We recommend RubyMine](https://www.elegantobjects.org/rubymine.svg)](https://www.jetbrains.com/ruby/)\n\n[![rake](https://github.com/yegor256/glogin/actions/workflows/rake.yml/badge.svg)](https://github.com/yegor256/glogin/actions/workflows/rake.yml)\n[![PDD status](https://www.0pdd.com/svg?name=yegor256/glogin)](https://www.0pdd.com/p?name=yegor256/glogin)\n[![Gem Version](https://badge.fury.io/rb/glogin.svg)](https://badge.fury.io/rb/glogin)\n[![Maintainability](https://api.codeclimate.com/v1/badges/155f86b639d155259219/maintainability)](https://codeclimate.com/github/yegor256/glogin/maintainability)\n[![Test Coverage](https://img.shields.io/codecov/c/github/yegor256/glogin.svg)](https://codecov.io/github/yegor256/glogin?branch=master)\n[![Yard Docs](https://img.shields.io/badge/yard-docs-blue.svg)](https://rubydoc.info/github/yegor256/glogin/master/frames)\n[![Hits-of-Code](https://hitsofcode.com/github/yegor256/glogin)](https://hitsofcode.com/view/github/yegor256/glogin)\n[![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/yegor256/glogin/blob/master/LICENSE.txt)\n\nThis simple gem helps you enable login/logout through\n[GitHub OAuth][doc]\nfor your web application. This is how it works with\n[Sinatra](http://www.sinatrarb.com/),\nbut you can do something similar in any framework.\n\nRead this blog post to get the idea:\n[_Simplified GitHub Login for a Ruby Web App_][blog]\n\nFirst, somewhere in the global space, before the app starts:\n\n```ruby\nrequire 'glogin'\nconfigure do\n  set :glogin, GLogin::Auth.new(\n    # Make sure these values are coming from a secure\n    # place and are not visible in the source code:\n    client_id, client_secret,\n    # This is what you will register in GitHub as an\n    # authorization callback URL:\n    'http://www.example.com/github-callback'\n  )\nend\n```\n\nNext, for all web pages we need to parse a cookie, if it exists,\nand convert it into a user:\n\n```ruby\nrequire 'sinatra/cookies'\nbefore '/*' do\n  if cookies[:glogin]\n    begin\n      @user = GLogin::Cookie::Closed.new(\n        cookies[:glogin],\n        # This must be some long text to be used to\n        # encrypt the value in the cookie.\n        secret\n      ).to_user\n    rescue GLogin::Codec::DecodingError =\u003e _\n      # Nothing happens here, the user is not logged in.\n      cookies.delete(:glogin)\n    end\n  end\nend\n```\n\nIf the `glogin` cookie is coming in and contains valid data,\na local variable `@user` is set to something like this:\n\n```ruby\n{ 'id' =\u003e '526301', 'login' =\u003e 'yegor256', 'avatar' =\u003e 'http://...' }\n```\n\nIf the `secret` is an empty string, the encryption is disabled.\n\nNext, we need a URL for GitHub OAuth callback:\n\n```ruby\nget '/github-callback' do\n  cookies[:glogin] = GLogin::Cookie::Open.new(\n    settings.glogin.user(params[:code]),\n    # The same encryption secret that we were using above:\n    secret\n  ).to_s\n  redirect to('/')\nend\n```\n\nFinally, we need a logout URL:\n\n```ruby\nget '/logout' do\n  cookies.delete(:glogin)\n  redirect to('/')\nend\n```\n\nIt is recommended to provide the third \"context\" parameter to\n`GLogin::Cookie::Closed` and `GLogin::Cookie::Open` constructors, in order\nto enforce stronger security. The context may include the `User-Agent`\nHTTP header of the user, their IP address, and so on. When anything\nchanges on the user side, they are forced to re-login.\n\nOne more thing is the login URL you need for your front page.\nHere it is:\n\n```ruby\nsettings.glogin.login_uri\n```\n\nFor unit testing, you can just provide an empty string as a `secret` for\n`GLogin::Cookie::Open` and `GLogin::Cookie::Closed`\nand the encryption is disabled: whatever comes from the cookie is trusted.\nFor testing it is convenient to provide a user name in a query string,\nlike:\n\n```text\nhttp://localhost:9292/?glogin=tester\n```\n\nTo enable that, it's recommended to add this line (see how\nit works in [zold-io/wts.zold.io](https://github.com/zold-io/wts.zold.io)):\n\n```ruby\nrequire 'sinatra/cookies'\nbefore '/*' do\n  cookies[:glogin] = params[:glogin] if params[:glogin]\n  if cookies[:glogin]\n    # same as above\n  end\nend\n```\n\nI use this gem in [sixnines](https://github.com/yegor256/sixnines)\nand [0pdd](https://github.com/yegor256/0pdd) web apps (both open source),\non top of Sinatra.\n\nAlso, you can use `GLogin::Codec` just to encrypt/decrypt a piece of text:\n\n```ruby\nrequire 'glogin/codec'\ncodec = GLogin::Codec.new('the secret')\nencrypted = codec.encrypt('Hello, world!')\ndecrypted = codec.decrypt(encrypted)\n```\n\n## How to contribute\n\nRead\n[these guidelines](https://www.yegor256.com/2014/04/15/github-guidelines.html).\nMake sure your build is green before you contribute\nyour pull request. You need to have\n[Ruby](https://www.ruby-lang.org/en/) 2.3+ and\n[Bundler](https://bundler.io/) installed. Then:\n\n```bash\nbundle update\nbundle exec rake\n```\n\nIf it's clean and you don't see any error messages, submit your pull request.\n\n[blog]: https://www.yegor256.com/2018/06/19/glogin.html\n[doc]: https://developer.github.com/apps/building-integrations/setting-up-and-registering-oauth-apps/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyegor256%2Fglogin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyegor256%2Fglogin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyegor256%2Fglogin/lists"}