Skip to content

Commit e693bcb

Browse files
authored
Fix CI, default to live over msal flow (#97)
* fix test error handling * default to live auth over msal * update docs
1 parent fcc959b commit e693bcb

File tree

11 files changed

+52
-22
lines changed

11 files changed

+52
-22
lines changed

.github/workflows/ci.yml

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313

1414
strategy:
1515
matrix:
16-
node-version: [14.x]
16+
node-version: [20.x]
1717

1818
steps:
1919
- uses: actions/checkout@v2
@@ -22,4 +22,6 @@ jobs:
2222
with:
2323
node-version: ${{ matrix.node-version }}
2424
- run: npm install
25-
- run: npm test
25+
- run: npm test
26+
env:
27+
MSAL_CLIENT_ID: ${{ secrets.MSAL_CLIENT_ID }}

README.md

+15-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# prismarine-auth
22
[![NPM version](https://img.shields.io/npm/v/prismarine-auth.svg)](http://npmjs.com/package/prismarine-auth)
33
[![Build Status](https://github.com/PrismarineJS/prismarine-auth/workflows/CI/badge.svg)](https://github.com/PrismarineJS/prismarine-auth/actions?query=workflow%3A%22CI%22)
4-
[![Discord](https://img.shields.io/badge/chat-on%20discord-brightgreen.svg)](https://discord.gg/GsEFRM8)
4+
[![Official Discord](https://img.shields.io/static/v1.svg?label=PrismarineJS&message=Discord&color=blue&logo=discord)](https://discord.gg/GsEFRM8)
55
[![Try it on gitpod](https://img.shields.io/badge/try-on%20gitpod-brightgreen.svg)](https://gitpod.io/#https://github.com/PrismarineJS/prismarine-auth)
66

77
Quickly and easily obtain auth tokens to authenticate with Microsoft/Xbox/Minecraft/Mojang
@@ -24,8 +24,6 @@ npm install prismarine-auth
2424
- [deviceType] {string} - See the [API.md](docs/API.md)
2525
- onMsaCode {Function} - (For device code auth) What we should do when we get the code. Useful for passing the code to another function.
2626

27-
[View more examples](https://github.com/PrismarineJS/prismarine-auth/tree/master/examples)
28-
2927
### Examples
3028

3129
### getMsaToken
@@ -39,6 +37,15 @@ const flow = new Authflow(userIdentifier, cacheDir)
3937
flow.getMsaToken().then(console.log)
4038
```
4139

40+
**Note**: By default, this library will authenticate as Minecraft for Nintendo Switch, with a `flow` set to `live`. For non-Minecraft applications you should
41+
register for Microsoft Azure Oauth token. See https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app#register-an-application for more information on obtaining an Azure token. You then use it with the `msal` flow like this:
42+
43+
```js
44+
const flow = new Authflow(userIdentifier, cacheDir, { flow: 'msal', authTitle: '000-000-000-000' })
45+
```
46+
47+
If `flow` is `live`, the default, then you can only specify existing Microsoft client IDs. This library exposes some default Microsoft client IDs under the exported `Titles` object. See the [types](./index.d.ts) for more information.
48+
4249
### getXboxToken
4350
See [docs/API.md](docs/API.md)
4451

@@ -71,6 +78,11 @@ flow.getMinecraftJavaToken().then(console.log)
7178
### getMinecraftBedrockToken
7279
See [docs/API.md](docs/API.md) and [example](examples).
7380

81+
### More
82+
[View more examples here](https://github.com/PrismarineJS/prismarine-auth/tree/master/examples).
83+
84+
See the [types](./index.d.ts) to checkout the full API.
85+
7486
## API
7587

7688
See [docs/API.md](docs/API.md)

docs/API.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## prismarine-auth
22

3+
See the [types](../index.d.ts) for additional information on the exposed API.
4+
35
### Authflow
46

57
This is the main exposed class you interact with. Every instance holds its own token cache.

index.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ declare module 'prismarine-auth' {
9494
}
9595

9696
export interface MicrosoftAuthFlowOptions {
97+
// If using Azure auth, specify an custom object to pass to MSAL
98+
msalConfig?: object
9799
authTitle?: Titles
98100
deviceType?: string
99101
deviceVersion?: string

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"description": "Authentication library for Microsoft, Xbox Live, and Minecraft with caching support",
55
"main": "index.js",
66
"scripts": {
7-
"test": "mocha --recursive --reporter spec --exit",
7+
"mocha": "mocha test/*.test.js --reporter spec --exit",
8+
"test": "npm run mocha",
89
"pretest": "npm run lint",
910
"lint": "standard",
1011
"fix": "standard --fix"

src/MicrosoftAuthFlow.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const JavaTokenManager = require('./TokenManagers/MinecraftJavaTokenManager')
1212
const XboxTokenManager = require('./TokenManagers/XboxTokenManager')
1313
const MsaTokenManager = require('./TokenManagers/MsaTokenManager')
1414
const BedrockTokenManager = require('./TokenManagers/MinecraftBedrockTokenManager')
15+
const Titles = require('./common/Titles')
1516

1617
async function retry (methodFn, beforeRetry, times) {
1718
while (times--) {
@@ -31,7 +32,7 @@ class MicrosoftAuthFlow {
3132
if (options && !options.flow) {
3233
throw new Error("Missing 'flow' argument in options. See docs for more information.")
3334
}
34-
this.options = options || { flow: 'msal' }
35+
this.options = options || { flow: 'live', authTitle: Titles.MinecraftNintendoSwitch }
3536
this.initTokenManagers(username, cache)
3637
this.codeCallback = codeCallback
3738
}
@@ -62,7 +63,12 @@ class MicrosoftAuthFlow {
6263
this.msa = new LiveTokenManager(this.options.authTitle, ['service::user.auth.xboxlive.com::MBI_SSL'], cache({ cacheName: this.options.flow, username }))
6364
this.doTitleAuth = true
6465
} else if (this.options.flow === 'msal') {
65-
const config = Object.assign({ ...msalConfig }, this.options.authTitle ? { auth: { ...msalConfig.auth, clientId: this.options.authTitle } } : {})
66+
let config = this.options.msalConfig
67+
if (!config) {
68+
config = structuredClone(msalConfig)
69+
if (!this.options.authTitle) throw new Error('Must specify an Azure client ID token inside the `authTitle` parameter when using Azure-based auth. See https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app#register-an-application for more information on obtaining an Azure token.')
70+
config.auth.clientId = this.options.authTitle
71+
}
6672
this.msa = new MsaTokenManager(config, ['XboxLive.signin', 'offline_access'], cache({ cacheName: 'msal', username }))
6773
} else {
6874
throw new Error(`Unknown flow: ${this.options.flow} (expected "live", "sisu", or "msal")`)

src/TokenManagers/MsaTokenManager.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ class MsaTokenManager {
127127
resolve(response)
128128
})
129129
}).catch((error) => {
130-
console.warn('[msa] Error getting device code')
130+
console.warn('[msa] Error getting device code. Ensure your supplied `authTitle` token (or clientId in your supplied MSAL config) is valid and that it has permission to do non-interactive code based auth.')
131131
console.debug(JSON.stringify(error))
132132
reject(error)
133133
})

src/common/Constants.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ module.exports = {
2020
},
2121
msalConfig: {
2222
// Initialize msal
23-
// Docs: https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/request.md#public-apis-1
23+
// Docs: https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/configuration.md#usage
2424
auth: {
2525
// the minecraft client:
2626
// clientId: "000000004C12AE6F",
File renamed without changes.

test/devicecode.js renamed to test/devicecode.test.js

+15-10
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,20 @@ const { expect } = chai
88
const crypto = require('crypto')
99
const curve = 'secp384r1'
1010

11-
describe('device code authentication', () => {
12-
it('should give us a token', (done) => {
13-
const onMsaCode = (code) => {
14-
if (!code) done(Error('missing user code'))
15-
if (code.userCode) done()
16-
}
17-
const flow = new Authflow('emailIdentifier@test.prismarine', './test', null, onMsaCode)
18-
flow.getXboxToken()
19-
})
11+
describe('device code authentication', function () {
12+
this.timeout(4000)
13+
if (process.env.MSAL_CLIENT_ID) {
14+
// Non-MSAL will be tested in Minecraft Bedrock condition below
15+
it('should give us a token (MSAL)', (done) => {
16+
const onMsaCode = (code) => {
17+
if (!code) done(Error('missing user code'))
18+
if (code.userCode) done()
19+
}
20+
const flow = new Authflow('emailIdentifier@test.prismarine', './test', { flow: 'msal', authTitle: process.env.MSAL_CLIENT_ID }, onMsaCode)
21+
flow.getXboxToken().catch(done)
22+
})
23+
}
24+
2025
it('should error if no certificate is present for bedrock', async () => {
2126
const flow = new Authflow('testauthflow', './test', { authTitle: Titles.MinecraftNintendoSwitch, flow: 'live' })
2227
await expect(flow.getMinecraftBedrockToken()).to.eventually.be.rejectedWith('Need to specifiy a ECDH x509 URL encoded public key')
@@ -30,6 +35,6 @@ describe('device code authentication', () => {
3035
const keypair = crypto.generateKeyPairSync('ec', { namedCurve: curve })
3136
const clientX509 = keypair.toString('base64')
3237
const flow = new Authflow('username', './test', { authTitle: Titles.MinecraftNintendoSwitch, flow: 'live' }, onMsaCode)
33-
flow.getMinecraftBedrockToken(clientX509)
38+
flow.getMinecraftBedrockToken(clientX509).catch(done)
3439
})
3540
})

test/password.js renamed to test/password.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ const chaiAsPromised = require('chai-as-promised')
44
chai.use(chaiAsPromised)
55
const { expect } = chai
66

7-
const { Authflow } = require('../')
7+
const { Authflow, Titles } = require('prismarine-auth')
88

99
describe('password authentication', async () => {
1010
it('should fail if not given a valid password', async () => {
11-
const flow = new Authflow('this.is.not@valid.email.lol', './test', { password: 'sdfasdfas', flow: 'msal' })
11+
const flow = new Authflow('this.is.not@valid.email.lol', './test', { password: 'sdfasdfas', flow: 'live', authTitle: Titles.MinecraftJava })
1212
await expect(flow.getXboxToken()).to.eventually.be.rejectedWith('Invalid credentials')
1313
})
1414
})

0 commit comments

Comments
 (0)