Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
@m10s/account-sdk-browser
Advanced tools
Welcome! This is the home of the Schibsted account JavaScript SDK for use by any website that wishes to use Schibsted account to sign up and log in users. Use it to generate URLs for your site's "Log in" button, query the logged-in status of your users, and to check whether they have access to products and subscriptions, etc.
This sdk mainly communicates with a service named Session Service, which is available on brand domains (i.e. id.vg.no) to avoid Third-Party Cookie request.
Since browsers started to block Third-Party Cookies, your top domain from local machine needs to match your Session Service top domain. Otherwise, the Session Service cookie will be a third-party cookie and will not be sent with a XHR request.
The same applies to cross scheme requests. The Session Service is hosted on https and therefore you need to run your site with HTTPS locally.
For example if your pre
domain is pre.sdk-example.com, and it uses id.pre.sdk-example.com Session Service
domain, your local domain should be local.sdk-example.com.
Do npm install --save @m10s/account-sdk-browser
Use this library as you would any other npm module: import { Identity } from '@m10s/account-sdk-browser'
With CommonJS it is possible to require
the Identity module
by appending /identity
.
Build your site as you prefer. This library uses modern JavaScript syntax (including async/await and other ES2017 and WHATWG features) by default. We recommend that you do any transpilation yourself for the browser versions you need to cater to. See this paragraph for info about our Babel-ified version and info about polyfills.
Initiate the SDK and provide at least clientId
, env
and sessionDomain
.
Currently supported envs include:
'DEV', 'PRE_NO', 'PRE_SE', 'PRE_DK', 'PRE_FI', 'PRO_NO', 'PRO_SE', 'PRO_DK', 'PRO_FI'
If this is for a new site and there is no sessionDomain yet, contact support to initiate the process.
Follow the migration guide.
Follow the migration guide.
showSimplifiedLoginWidget
accepts the same params as login function (state
is required, it might be string or async function). If the simplified login prompt is to be loaded, showSimplifiedLoginWidget
will return true
.There is an example that demonstrates how the SDK can be used. The code is here, and you can see it live here. You have a use-case that we haven't thought of? Ask us to add it by creating an issue or on slack.
You can use that code as inspiration or just fork and play with it. The account-sdk-browser NPM module is used for authenticating the user with Schibsted account. Take a look at how the SDK is initialized.
When a user wants to log in to your site, you direct them to a UI flow that is hosted by Schibsted
Account. We authenticate the user and redirect them back to your site. This final redirect back to
your site is done in accordance with the OAuth2 spec. That means that we pass a code
in the query
string in that redirect uri. You can use that code
on your site backend along with your client
credentials (client id & secret) to get an Access Token (AT) and Refresh Token (RT). You don't
send the AT (and never ever the RT!) to the browser but rather keep it on the server side and
associate it with that particular user session in order to be able to call Schibsted account APIs on
behalf of that user.
The SDK fires events when something we deem interesting is happening. For example the
Identity class
emits some events when the user is logged in or logged out. This SDK uses a familar interface that's
very similar to Node's EventEmitter. The most important
methods are .on(eventName, listener)
(to subscribe to an event) and .off(eventName, listener)
(to unsubscribe to an event).
Let's start with a bit of example code:
import { Identity } from '@m10s/account-sdk-browser'
const identity = new Identity({
clientId: '56e9a5d1eee0000000000000',
redirectUri: 'https://awesomenews.site', // ensure it's listed in selfservice
env: 'PRE', // Schibsted account env. A url or a special key: 'PRE', 'PRO', 'PRO_NO', 'PRO_FI' or 'PRO_DK'
sessionDomain: 'https://id.awesomenews.site', // client-configured session-service domain
})
async function whenSiteLoaded() {
const loginContainer = document.getElementById('login-container')
if (await identity.isLoggedIn()) {
const user = await identity.getUser()
const span = document.createElement('span')
span.textContent = `Hello ${user.givenName}`
loginContainer.appendChild(span)
} else {
loginContainer.innerHTML = '<button class="login-button">Log in</button>'
}
}
function userClicksLogIn() {
identity.login({ state: 'some-random-string-1234-foobar-wonky-pig' })
}
state
This parameter is an OpenID Connect parameter (described in this paragraph in the spec). It's formatted as an opaque string. This means you can send anything that can be serialized to a string. In practice, we have good experience sending something like a JSON value like a base64-url-encoded value — it's just an easy way to avoid browsers or backends messing with special characters.
But as a trivial example, if you call Identity.login(..)
with params
redirectUri=https://site.com&state=article%3D1234
— then at the end of the authentication flow,
the user will be sent back to your redirectUri, and the state
parameter will be forwarded along
with the auth code
parameter.
It is recommended that you provide a unique identifier as part of the state, to prevent CSRF attacks. For example this can be accomplished by:
1234abcd
, saves it in some tokenCache, and forwards to
your browser frontendIdentity.login
with state = base64Urlencode({ token: '1234abcd', article: '1234', ... })
code
(which it can exchange for OAuth tokens for the user) and state
decodedState = base64Urldecode(query.state)
and then verify that its
tokenCache.contains(decodedState.token)
. If that fails, then possibly a CSRF attack was
attempted. If successful, remove the token from the tokenCache so the same token can't be used
again, and continue to show decodedState.article
Although Schibsted account abstracts away the details of how the users sign up or log in, it's worth mentioning that your end users have a few ways to log in:
AMR
claim of IDTokenThe default is username & password. If you wish to use one of the passwordless login methods, the
login()
function takes an optional parameter called acrValues
(Authentication Context Class Reference).
The acrValues
parameter with multifactor authentication can take following values:
eid
- authentication using BankID (for DEV and PRE environments you can choose between country specific solution by specifying eid-no
or eid-se
instead)otp-email
- passwordless authentication using code sent to registered emailpassword
- force password authentication (even if user is already logged in)otp
- authentication using registered one time code generator (https://tools.ietf.org/html/rfc6238)sms
- authentication using SMS code sent to phone numberpassword otp sms
- those authentication methods might be combinedThe classic way to authenticate a user, is to send them from your site to the Schibsted account domain, let the user authenticate there, and then have us redirect them back to your site. If you prefer, we also provide a popup that you can use. In this method, the authentication happens on a separate popup window and at the end of the auth flow. We recommend that you make the popup send a signal to your main page — using postMessage or something similar — to indicate that the user is logged in. If the popup window fails to open, it'll automatically fall back to the redirect flow. The SDK Example project mentioned above demonstrates how it can work. Again, you can see sdk-example if you want a working example.
Schibsted account relies on browser cookies to determine whether a user is recognized as logged in. The SDK provides functions that can be used to check if the user that's visiting your site is already a Schibsted user or not.
isLoggedIn=true
and at the
same time isConnected=false
if they have logged in to Schibsted account, but not accepted terms
and privacy policy for your site.If you've lately changed your terms & conditions, maybe the user still hasn't accepted them. In that case they are considered not connected. In that case, if they click "Log in" from your site, we will just ask them to accept those terms and redirect them right back to your site.
If you want to log the user out of Schibsted account, you can call Identity#logout. This will remove the Schibsted account brand session. User will still be logged into Schibsted account.
This SDK uses modern JavaScript features. If you support older browsers, you should use a tool like babel to transform the JavaScript as needed. However, since certain teams have deployment pipelines where it's difficult to do their own transpilation, we do provide some opt-in es5 files as well:
@m10s/account-sdk-browser/es5
: Include Identity
.@m10s/account-sdk-browser/es5/global
: Include Identity
. In addition, add it as a variable to the global window
object.@m10s/account-sdk-browser/es5/identity
can be used to directly include the class by itself.But then regardless of whether you use the es5 versions or not, you might need to polyfill certain
things that might be missing in the browsers you wish to support. A quick test using IE11 showed
that we needed polyfills for Promise
, URL
, Object.entries
, fetch
, Number.isFinite
and
Number.isInteger
.
There are some cookies used by Schibsted account. They should all be considered opaque on the browser side. Nevertheless, here is a short description of them.
vgs_email
, because reasons (on PRE, it is called spid-pre-data
).
It's a JSON string that's encoded using the standard encodeURIComponent()
function and is an
object that contains two pieces of information that's important:
remember
: if set to true
, the user chose to be remembered and this means we usually support
auto-login (that is, if you call the Schibsted account hassession service, and no session can
be found in the session database, it will automatically create a new one for the user so that
they don't have to authenticate again. If it is false
, it should be interpreted as the user
does not want to be automatically logged in to any site when their session expiresv
: the version numberidentity
, and SPID_SE
or
SPID_NO
. It contains:
user
: an object (if it's missing, a call to hassession will return a 401
with a
UserException
that says No session found
)
userId
identifies the user. We use this property to compare "old" user with "new" user and
fire events that indicate that the user has changedis_logged_in
indicates if the user is logged inuser_tags
: a map that contains some flags about the user; namely:
is_logged_in
indicates if the user is logged in (this seems to be a duplicate of a
property with a similar name in the parent user
object)terms
: a map of term ids that indicate if they've been accepted by the user.referer
(yep, missing the double "rr"..): If this is missing, a call to hassession will
return a 401
with a UserException
that says No session found
.Tags are pushed to NPM via Travis. To release a new version, run in master
$ npm version <major|minor|patch>
which will run the test, update version in package.json, commit, tag the commit and push.
Copyright (c) 2024 Schibsted Products & Technology AS
Licensed under the MIT License
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
FAQs
M10s account SDK for browsers
We found that @m10s/account-sdk-browser demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.