Skip to content

Instantly share code, notes, and snippets.

@damaneice
Last active January 29, 2024 21:03
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save damaneice/a2aa8b19e698876ed37626a6b7b861ff to your computer and use it in GitHub Desktop.
Save damaneice/a2aa8b19e698876ed37626a6b7b861ff to your computer and use it in GitHub Desktop.
How to deliver GitHub Education benefits to your students

Hello! This documentation has been deprecated - you can find the updated documentation at https://gist.github.com/jen-k/73e5dae57526ecf73d8475e2f59a3f9a

Deprecated documentation

How to deliver GitHub Education benefits to your students

Students at your school can quickly claim their GitHub Education benefits by visiting a unique web address. By visiting that address, GitHub will verify the student's academic status with your school and instantly deliver their benefits to them.

Your school can create a unique web address for each student by including three things in it:

  1. school_id: Your school’s unique identifier, provided by GitHub.

  2. student_id: The individual student’s unique identifier, defined by your school.

  3. signature: A code used to authenticate the message, produced by your school using an algorithm (instructions below).

Used together, your school can deliver each student a unique web address that looks something like this:

https://education.github.com/student/verify?school_id=1&student_id=1&signature=b89099fdb8a24b0e2ef8ab0de893bb9408392cbf84e8fb9186adb84a920c536c

How to produce each student’s ‘signature’

The algorithm you’ll use to create each student’s signature requires the aforementioned school_id and student_id, as well as an additional GitHub-provided secret_key.

The algorithm requires that each of these values be passed as strings -- not numerals.

Here, for example, is how you can then produce a student’s signature using Ruby:

signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), secret_key, school_id + student_id)

What students should expect

When a student receives their unique web address from your school, they can visit that address in any web browser. If they are already signed into GitHub on that browser, they’ll see a GitHub Education web page confirming that they’ve been verified.

screen shot 2018-07-09 at 10 11 02 am

If they’re not yet signed in, the student will simply be asked to sign in before seeing the confirmation web page.

@orboan
Copy link

orboan commented Dec 4, 2018

Hello,
would you be so gentle and provide a snippet in Java to generate the signature?
Thank you.

@orboan
Copy link

orboan commented Dec 13, 2018

This instructions are only valid for schools where Ruby is used. As we do use Java, the question is, are we going to get the proper instructions to get the Student Pack? When signing the papers we weren't told that knowing Ruby was a requirement. Thanks

@kvirani
Copy link

kvirani commented Jan 24, 2019

@orboan it seems to me that Ruby is not a requirement. They simply showed an example using Ruby to illustrate which types of algorithms are required to sign the request. A quick google for openssl HMAC java yields this repo that shows examples in other languages.

@fireromu
Copy link

@orboan This should do what you're looking for. Just fill in the values for student_id, school_id and your secret_key.

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class Generate_GitHub_Education_Signature {
  public static void main(String[] args) {
    String student_id = "...";
    String school_id  = "...";
    String secret_key = "...";
    
    String ALGORYTHM  = "HmacSHA256";
    String EDU_URL = "https://education.github.com/student/verify?school_id=%s&student_id=%s&signature=%s";
    String msg = school_id + student_id;
    String signature = null;
    try {
      Mac mac = Mac.getInstance(ALGORYTHM);
      mac.init(new SecretKeySpec((secret_key).getBytes("UTF-8"), ALGORYTHM));
      byte[] bytes = mac.doFinal(msg.getBytes("ASCII"));

      StringBuffer hash = new StringBuffer();
      for (int i = 0; i < bytes.length; i++) {
        String hex = Integer.toHexString(0xFF & bytes[i]);
        if (hex.length() == 1) {
          hash.append('0');
        }
        hash.append(hex);
      }
      signature = hash.toString();
    } catch (UnsupportedEncodingException e) {
    } catch (InvalidKeyException e) {
    } catch (NoSuchAlgorithmException e) {
    }
    
    String url = String.format(EDU_URL, school_id, student_id, signature);
    System.out.println(url);
  }
}

@dopch
Copy link

dopch commented Oct 15, 2019

If someone need it in Python3 (Tested on Python3.7.4)
usage: Github_edu_link_generator.py [-h] student_id

Github Education link generator.

positional arguments:
student_id Unique individual student’s identifier, defined by your school (integer).

optional arguments:
-h, --help show this help message and exit

#!/usr/bin/python3
## Github Education link generator 
## ----------------------------------------------------------------------------
## "THE BEER-WARE LICENSE" (Revision 42):
## Thomas Nogueira <t.nogueira94@gmail.com> wrote this file. As long as you retain this notice you
## can do whatever you want with this stuff. If we meet some day, and you think
## this stuff is worth it, you can buy me a beer in return.
## https://www.codam.nl/
## ----------------------------------------------------------------------------


import argparse
import hmac
import hashlib


def generator(args: argparse.Namespace):
    secret_key = b'YOURSECRETKEY'
    school_id = YOURSCHOOLID
    message = (str(school_id) + str(args.student_id)).encode('ASCII')
    signature = hmac.new(secret_key, message, digestmod=hashlib.sha256).hexdigest()
    print(f"https://education.github.com/student/verify?school_id={school_id}&student_id={args.student_id}&signature={signature}")

def main():
    parser = argparse.ArgumentParser(description="Github Education link generator.")
    parser.add_argument('student_id', type=int, help="Unique individual student’s identifier, defined by your school (integer).")
    args = parser.parse_args()
    generator(args)


if __name__ == '__main__':
    main()

Sincerely,
Thomas

@karlhorky
Copy link

karlhorky commented Oct 21, 2019

Edit: Full repository (also with Ruby and JavaScript versions): https://github.com/upleveled/github-education-generate-student-url

In case you have openssl installed and would like to generate the URL from the command line, here's a shell script that will take a student_id as an argument (replace the placeholders like <school_id> with your data):

#!/usr/bin/env bash

gen_student_link () {
  local school_id=<school_id>
  local student_id=$1
  local secret_key=<secret_key>
  echo "https://education.github.com/student/verify?school_id=${school_id}&student_id=${student_id}&signature=$(printf ${school_id}${student_id} | openssl dgst -sha256 -hex -hmac ${secret_key})"
}

gen_student_link $1

One it's defined, use the script like:

./gen_student_link.sh <student_id>

For a one-off command with global variables, try this instead:

SCHOOL_ID=<your school_id> &&\
  STUDENT_ID=<your student's student_id> &&\
  SECRET_KEY=<your secret_key> &&\
  echo "https://education.github.com/student/verify?school_id=${SCHOOL_ID}&student_id=${STUDENT_ID}&signature=$(printf ${SCHOOL_ID}${STUDENT_ID} | openssl dgst -sha256 -hex -hmac ${SECRET_KEY})"

Or, to generate just the signature:

printf <school_id><student_id> | openssl dgst -sha256 -hex -hmac <secret_key>

@karlhorky
Copy link

karlhorky commented Jan 29, 2020

I made my solution using the command line / shell / terminal with OpenSSL above into a full repository:

https://github.com/upleveled/github-education-student-url-openssl/

Edit: Now with JavaScript and Ruby Versions:

https://github.com/upleveled/github-education-generate-student-url

@van100j
Copy link

van100j commented Feb 4, 2020

We've used this generateStudentUrl function with Node.js, to generate unique URLs for our students:

const crypto = require('crypto')

const generateStudentUrl = (studentId, schoolId, secretKey) => {
    const signature = crypto.createHmac('sha256', secretKey)
        .update(`${schoolId}${studentId}`)
        .digest('hex');

    return `https://education.github.com/student/verify?school_id=${schoolId}&student_id=${studentId}&signature=${signature}`
}

// log the unique web address for student with student_id=YOUR_STUDENT_ID in the console
console.log(generateStudentUrl('YOUR_STUDENT_ID', 'YOUR_SCHOOL_ID', 'YOUR_SECRET_KEY'))

// export it, to use the `generateStudentUrl` function elsewhere in your code
module.exports = generateStudentUrl

@karlhorky
Copy link

Awesome, nice one @van100j!

@pensierinmusica
Copy link

@damaneice it seems like the school_id can't contain certain characters (e.g. "%"). This took us quite a while to debug.

Could you please update the documentation to say exactly what format is allowed for the student ID? It'd be important.

For example, what is the max length, the minimum length, and the characters allowed.

Thanks!

@jen-k
Copy link

jen-k commented Apr 21, 2020

Hey @pensierinmusica,

@damaneice is no longer on this project, but I'll ping another engineer on the team to see if I can determine the invalid characters. We're short-staffed at the moment, but we'll get this updated! Thanks!

@karlhorky
Copy link

@jen-k Re: validation, in case the team would want to co-maintain / take over the URL generator repo I created (and add the validation rules there in Ruby + JavaScript + Shell code), here is a link:

https://github.com/upleveled/github-education-generate-student-url

@pensierinmusica
Copy link

pensierinmusica commented May 3, 2020

@jen-k awesome, thx! 🙂

@RomainDelamare
Copy link

RomainDelamare commented Jun 22, 2020

If someone need in C#

var userId = ...;
var schoolId = ...;
var secret = ...;
var githubUrl = "https://education.github.com/student/verify?school_id={0}&student_id={1}&signature={2}";

byte[] keyByte = new ASCIIEncoding().GetBytes(secret);
byte[] messageBytes = new ASCIIEncoding().GetBytes(string.Concat(schoolId, userId));
byte[] hashmessage = new HMACSHA256(keyByte).ComputeHash(messageBytes);

StringBuilder hex = new StringBuilder(hashmessage.Length * 2);
foreach (byte b in hashmessage)
{
    hex.AppendFormat("{0:x2}", b);
}

var signature =  hex.ToString();
var url = string.Format(githubUrl, schoolId, userId, signature);

@jasicarose75
Copy link

thanks

@W1zarDddD
Copy link

W1zarDddD commented Jan 24, 2024

Provide students with invites to the GitHub Classroom organization. Train them to use Git and GitHub for collaborative development. I personally found dissertation topics in one invite, but they had already been sorted out, I had to use https://papersowl.com/blog/ideas-for-dissertation-topics for help. In general, you can come up with a lot of things to interest students. All this will provide students with access to powerful development and learning tools.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment