davidsichau:accounts-eduid

v1.0.5Published last month

This repo contains in packages the davidsichau:accounts-eduId package.

The rest is only for testing.

To use this package:

import React from 'react';

import {
  LoginRedirect as LoginEduId,
  LoginPopUp,
  SwitchEduIdImage,
} from 'meteor/davidsichau:accounts-eduid';
import useCurrentUser from './hooks/useCurrentUser';

function App() {
  const user = useCurrentUser();
  const [startLogin, setStartLogin] = React.useState('');

  return (
    <div className="container">
      <header>
        <h1>Login</h1>
      </header>

      <button
        onClick={() => {
          setStartLogin('eduId');
        }}
      >
        <SwitchEduIdImage style={{ height: '20px' }} />
      </button>

      <LoginPopUp loginLabel="popup" />

      {startLogin === 'eduId' ? (
        <LoginEduId loginStyle="redirect" loginLabel="Login Popup" />
      ) : null}

      {user ? <div>login success</div> : null}
      {user ? <button onClick={() => Meteor.logout()}>logout</button> : null}
    </div>
  );
}

export default App;
>

oAuth Helper

Helper for et oAuth Login

Getting Started

install the package with meteor:

meteor add davidsichau:accounts-eduId

Login

Provided Functions

The package provides a function for oAuth Login via the oAuth system.

Meteor.loginWithEduId({loginStyle: 'popup'}, callback);

Where loginStyle can bei either popup or redirect depending on the wanted kind of login way. This function then will start the oAuth login flow and when the callback is called the user is logged in. callback is the standard callback of meteor login methods.

Provided Components

The package provides a react component which takes care of the login.

import { LoginRedirect, LoginPopUp } from 'meteor/davidsichau:accounts-eduId'

redirect flow

If the user is not logged in the Component will redirect the user to the oAuth Login page and after wards redirect the user back.

The component will render a button with the class .oAuthPopupButton (which can be styled with css). When the user clicks the button a popup opens with the oAuth Login page. The label of the button can be provided by the loginLabe prop of the LoginPopUp component.

Configuration

To create a new jwk use the following command:

jose jwk gen -i '{"alg": "ES256", "kty":"EC","crv":"P-256", "use": "sig"}' -o key.jwk -s

In order that the package works it is required to provide the following document in the meteor_accounts_loginServiceConfiguration collection:

{
{
    "_id" : string
    "service" : "eduId",
    "client_id" : "ethz-dinkf-edtools_testing2", 
    "redirect_uri" : "http://localhost:3010/_oauth/eduId",
    "affiliationSecret" : "ethz-inf:SECRET",
    "discoverUrl" : "https://login.test.eduid.ch/.well-known/openid-configuration",
    "key" : {
        "keys" : [ 
            {
                "kty" : "EC",
                "d" : SECRET,
                "use" : "sig",
                "crv" : "P-256",
                "x" : "32DEI_k77PEkod0DZzQOOTvRsOVW2pgAkEu5t_I52OE",
                "y" : "AyUwuzhIodJKxNf5Dgvm8tSxoDfQiUzhRMwdklJiXiU",
                "alg" : "ES256"
            }
        ]
    }
}
}
  • service is the name of the login service and is fixed to eduId.
  • client_id is the provided client id of the oAuth Server
  • redirect_uri The local url the oauth server should redirect the client to.
  • affiliationSecret The secret to access the affiliationAPI.
  • key the JSON Web Key (JWK)

User Collection

If a login is successful a new user is generated or if the user already exist the user is logged in.

An example user looks like that:

{
    "_id" : "AcgweGSX36T3Bcx7o",
    "createdAt" : ISODate("2018-04-25T12:02:04.129Z"),
    
    "services" : {
        "eduId" : {
    "id" : "0000431030959828@test.eduid.ch",
    "access_token" : "AApzZWNyZXQxNTYwI8B722MMimVFIiJinFup6Xny9t8l9xirtwkaH4DVqvGpigIxdF1_0MJiJD5ePN43s-zZMX_VBUAKFN9l8xI3yPJjAf_O0H1FVDSToUvUKgDm_dOImQUDEj5FyiCKR2joSmxGb6LNgXpn2g_B-6XuTzqGmJ94mAWCXLH_wpdHwm-MqyYQ_oiBaDkwZr9EcMi_LpvNOtpe1-Anfgo6YkOydFspghV0mR_dTB2A3nRYmx3dFUebSiGWgD4hRu0xgAdDi2pOaiopPjh54MiwqtAO0KjP61mQhUE3gTfsBRp_6YcDdegZwd1bLRrTpeN0Oeg9zfh76BrERGZ4TZPJvdBaFxTtTTi1j7lnXl_1EUACip_TXT18-frkScVxUtDmbdlZL-KtGS1uhL0Uavlo62xVPPg3_7o0QQpMJgZNjroDdkg8Ek224b86iS9mDvD-o5vXSH2ZzuezvkmtISyhu9s9k50V6HFZlbbVY56-WZoLSEaL72YoyawRT7fmwvFYuOru_-5gO8P4jFD3DcX3qV4CZpbZAbtoVoWhUWTtIYMvwZO-WfHY7roeJU7j6aAACGtdMTJzMBBKW241-DVi77c",
    "id_token" : "eyJraWQiOiJkZWZhdWx0UlNBU2lnbiIsImFsZyI6IlJTMjU2In0.eyJhdF9oYXNoIjoiaVZhaEpNd21oNUhVa0dRclVuRHU4USIsInN1YiI6IkE3QzNaVDdGTDdUT0o2UVJaSVVQTjRRN0tEVEw1WTJHIiwiYXVkIjoiZXRoei1kaW5rZi1lZHRvb2xzX3Rlc3RpbmcyIiwiYWNyIjoicGFzc3dvcmQiLCJzd2lzc0VkdVBlcnNvblVuaXF1ZUlEIjoiMDAwMDQzMTAzMDk1OTgyOEB0ZXN0LmVkdWlkLmNoIiwiYXV0aF90aW1lIjoxNjMwMzI1OTYzLCJpc3MiOiJodHRwczpcL1wvbG9naW4udGVzdC5lZHVpZC5jaFwvIiwiZXhwIjoxNjMwMzQwMzYzLCJpYXQiOjE2MzAzMjU5NjMsInN3aXNzRWR1SURMaW5rZWRBZmZpbGlhdGlvblVuaXF1ZUlEIjpbIkYyQzZBQUIzLTkzQkUtNDkzNi1BMkZGLUQ0OUZCQjJCMzNBNUB6aGF3LmNoIiwiMTA0Mjg0QGV0aHouY2giXX0.DElMgkBKqb_KZehh8E-ctwInlHUGHQhHKtW2JuS7MyZ-n493KC9KFevN3NS_jSlgeCbvbVZvhJSuovH7gFYCu2ZCnNW6jv6ciSTHE6E-758tZRPeAskzyz1twziQZvpbzH3STdOyKex_PB-xgEXtAeDX3cZxtWbUa05UbdFQXPh0E71BJE1k7mZjjQ5H4FvA2iVQ4l9sHEIR3ODQwA7Y7VMv8gwo8ABAE-XDAQgnPWg1VA0Qw8pq3tUp0PRTUe2HGWxzFko6H-ras5qr7N-O5Ba1t0xoogu24Y1pd5Pvnj2ivQzgcvvATzDs6MiHMoQtw644EmF2jPsOXFLWsjzz8A",
         "token_type" : "Bearer",
         "expires_at" : 1630326263
        },
        "resume" : {
            "loginTokens" : []
        }
    },
    "profile" : {
    "firstName" : "David",
    "lastName" : "Sichau",
    "legiNummer" : "08-934-739",
    "gender" : "m",
    "swissEduPersonUniqueID" : "0000431030959828@test.eduid.ch",
    "swissEduIDLinkedAffiliationUniqueID" : [ 
        "F2C6AAB3-93BE-4936-A2FF-D49FBB2B33A5@zhaw.ch", 
        "104284@ethz.ch"
    ],
    "swissEduIDLinkedAffiliationMail" : [ 
        "sichau@inf.ethz.ch", 
        "sichadav@students.zhaw.ch"
    ],
    "swissEduIDAssociatedMail" : [ 
        "dsichau@gmail.com"
    ],
    "email" : "sichau@inf.ethz.ch",
    "language" : "de"
}
}

In services et the original user id on the oAuth server is stored and the accessToken, which is required if one wants to call any specific oAuth Server methods in the user context.

To update the package

Run meteor publish inside the accounts-et folder to publish a new version. You should increase the version number for each update.

Useful hooks:

Is called for every oauth login. User is only defined if it already existed.

Accounts.onExternalLogin((options, user) => {
    console.log(options);
    console.log(user);

    options.profile.blub = 'test';
    return options;
});

Use this to merge user

Accounts.onCreateUser((options, user) => {
    console.log('onCreateUser');
    console.log(options);
    console.log(user);

    const customizedUser = {
        _id: options.profile.userId,
        user,
    };
        <button onClick={() => { setStartLogin(true)}}>start login</button>
        {startLogin ? <Login loginStyle='redirect' loginLabel='Login Popup'/> : null}
    // We still want the default hook's 'profile' behavior.
    if (options.profile) {
        customizedUser.profile = options.profile;
    }

    return customizedUser;
});